#!/usr/bin/perl
#  Copyright 2001-2023 Leslie Richardson

#  This file is part of Open Admin for Schools.

# Get Grade and Year-Month and display attendance for each day.

# Jun3 16, 2023 - fix layout of month selection. Split after 5 months.
# June 13, 2023 - Fix ordering of multiple months reporting.

# Update: Jan 10, L520, section updated to correctly join days closed
# with partial days closed for homerooms.




my %lex = ('Teacher' => 'Teacher',
	   'Error' => 'Error',
	   'Main' => 'Main',
	   'Attendance' => 'Attendance',
	   'Report' => 'Report',
	   'Months' => 'Months',
	   'Continue' => 'Continue',
	   'Select' => 'Select',
	   'Grade' => 'Grade',
	   'Student' => 'Student',
	   'Course' => 'Course',
	   'Reason' => 'Reason',
	   'Late' => 'Late',
	   'Days Open' => 'Days Open',
	   'Days Closed' => 'Days Closed',
	   'Show' => 'Show',
	   'Withdrawn' => 'Withdrawn',
	   'or' => 'or',
	   'Homerooms' => 'Homerooms',
	   'Missing' => 'Missing',
	   'Value' => 'Value',
	   'WD' => 'WD',
	   'Enrolled' => 'Enrolled',
	   'Attended' => 'Attended',
	   'View' => 'View',
	   'Hover' => 'Hover',
	   'Click' => 'Click',
	   'Edit' => 'Edit',
	   'Override' => 'Override',
	   'Periods per Day' => 'Periods per Day',
	   'Not Found' => 'Not Found',
	   'Period' => 'Period',
	   'Method' => 'Method',
	   'Absent' => 'Absent',
	   'Present' => 'Present',
	   'No Entry' => 'No Entry',
	   'OK' => 'OK',
	   'Skip' => 'Skip',
	   'Students' => 'Students',
	   'Homeroom' => 'Homeroom',
	   'Monthly' => 'Monthly',

	   );

my $self = 'rptmonth4.pl';

my $closedcolor = '#AAA';
my $partclosedcolor = '#EEE';
my $notenrolledcolor = '#DDD';

use DBI;
use CGI;
use Cwd;
use Time::JulianDay;
use Number::Format qw(:all);


# Get current dir so know what path for config files.
my $configpath;
my $teachermode;
if ( getcwd() =~ /tcgi/ ){ # we are in tcgi
    $teachermode = 1;
    $configpath = '..'; # go back one to get to etc.
} else {
    $configpath = '../..'; # go back two to get to etc.
}

# only load passwords and users
eval require "$configpath/etc/admin.conf.root";
if ( $@ ) {
    print $lex{Error}. " $@<br>\n";
    die $lex{Error}. " $@\n";
}

eval require "$configpath/lib/libattend.pl";
if ( $@ ) {
    print $lex{Error}. " $@<br>\n";
    die $lex{Error}. " $@\n";
}

eval require "$configpath/lib/libschedule.pl";
if ( $@ ) {
    print $lex{Error}. " $@<br>\n";
    die $lex{Error}. " $@\n";
}

eval require "$configpath/lib/libDate.pl";  # functions to check partial day closure vals; grades field.
if ( $@ ) {
    print $lex{Error}. " $@<br>\n";
    die $lex{Error}. " $@\n";
}


my $dbtype = 'mysql';
my $dsn = "DBI:$dbtype:dbname=$dbase";
my $dbh = DBI->connect($dsn,$user,$password);



# Load Configuration Variables;
my $sth = $dbh->prepare("select id, datavalue from conf_system where filename = 'admin'");
$sth->execute;
if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
while (	my ($id, $datavalue) = $sth->fetchrow ) {
    eval $datavalue;
    if ( $@ ) {
	print qq{$lex{Error}: $@<br>\n};
	die "$lex{Error}: $@\n";
    }
}

=head
my $sth = $dbh->prepare("select id, datavalue from conf_system where dataname = ?");
foreach my $field ( css ) {
    $sth->execute( $field );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while (	my ($id, $datavalue) = $sth->fetchrow ) {
	eval $datavalue;
	if ( $@ ) {
	    print qq{$lex{Error}: $@<br>\n};
	    die "$lex{Error}: $@\n";
	}
    }
}
=cut


# Teachermode
if ( $teachermode ) { # running on teacher site
    $css = $tchcss;
    $homepage = $tchpage;
    $downloaddir = $tchdownloaddir;
    $webdownloaddir = $tchwebdownloaddir;
}


my $q = new CGI;
print $q->header( -charset, $charset );
my %arr = $q->Vars;



# Set Date
my @tim = localtime(time);
my $cyear = @tim[5] + 1900;
my $cmonth = @tim[4] + 1;
my $cday = @tim[3];
my $currdate = "$cyear-$cmonth-$cday";
my $currjd = julian_day( split('-', $currdate) );
my $curryrmo = "$cyear-$cmonth";

my $title = "$lex{Monthly} $lex{Attendance} $lex{Report} 4";
print qq{$doctype\n<html><head><title>$title</title>\n};
print qq{<link rel="stylesheet" href="$css" type="text/css">\n};
print qq{<style>th.dr, td.dr { border-right-style:double; border-right-width:4px; }</style>\n};

print qq{$chartype\n</head><body style="padding:1em;">\n};

print qq{[ <a href="$homepage">$lex{Main}</a> \n};
if ( not $teachermode ) {
    print qq{| <a href="$attpage">$lex{Attendance}</a> \n};
}
print qq{]\n<h1>$title</h1>\n};


if ( not $arr{page} ) {
    showStartPage();

} elsif ( $arr{page} == 1 ) {
    delete $arr{page};
    doReports();
}





#----------------
sub showStartPage {
#----------------

    my $checkString = qq{checked="checked"};
    my ($checkHR, $checkGR);
    if ( $arr{checkHR} ) {
	$checkHR = $checkString;
    }
    if ( $arr{checkGR} ) {
	$checkGR = $checkString;
    }

    

    # Setup Year-Months.
    my @months;
    my %months;


    my ($sy, $sm, $sd) = split('-', $schoolstart); # schoolstart is global var from config.
    my $yrmo = "$sy-$sm";
    push @months, $yrmo;
    $months{$yrmo} = "$s_month[$sm]-$sy";

    for my $i (1..10) {
	my $mo = $sm + $i;
	my $yr = $sy;
	if ( $mo > 12 ) {
	    $mo = $mo - 12;
	    $yr++;
	}

	if ( length $mo == 1 ) { $mo = '0'. $mo; }
	my $yrmo = "$yr-$mo";
	push @months, $yrmo;
	$months{$yrmo} = "$s_month[$mo]-$yr";

	if ( $yr == $cyear and $mo == $cmonth ) { # done
	    last;
	}
	
    }


    # Get the grades, for course attendance.
    my @grades;
    my $sth = $dbh->prepare("select distinct grade from student 
      where grade is not NULL and grade != ''");
    $sth->execute;
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $gr = $sth->fetchrow ) {
	if ( $g_AttendanceEntryMethod{$gr} eq 'subject' ) {
	    push @grades, $gr;
	}
    }


    # Get the homerooms.
    my @homerooms;

    my $sth1 = $dbh->prepare("select distinct grade from student where homeroom = ? 
      and grade != '' and grade is not NULL");

    my $sth = $dbh->prepare("select distinct homeroom from student where 
     homeroom is not NULL and homeroom != ''");
    $sth->execute;
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $hr = $sth->fetchrow ) {

	push @homerooms, $hr; # removed checking below
	# Now check for the grade level in this homeroom
#	$sth1->execute($hr);
#	if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
#	while ( my $gr = $sth1->fetchrow ) {
#	    if ( $g_AttendanceEntryMethod{$gr} eq 'homeroom' ) {
#		push @homerooms, $hr;
#		last;
#	    }
#	}
    }


    # Check all homerooms
    print qq{<form action="$self" method="post" style="display:inline;">\n};
    print qq{<input type="hidden" name="checkHR" value="1">\n};
    print qq{<input type="submit"  value="Select All Homerooms">\n};
    print qq{</form>\n};

    # Check All Course Attendance Grades
    print qq{<form action="$self" method="post" style="display:inline;">\n};
    print qq{<input type="hidden" name="checkGR" value="1">\n};
    print qq{<input type="submit"  value="Select All Course Attendance Grades">\n};
    print qq{</form>\n};

    print qq{<div style="margin:1em;"></div>\n};

    
    print qq{<form action="$self" method="post">\n};
    print qq{<input type="hidden" name="page" value="1">\n};

    print qq{<table cellpadding="3" border="0" cellspacing="0">\n};

    # Select Months
    print qq{<tr><td class="bra">$lex{Select} $lex{Months}</td>};
    print qq{<td class="la">\n};
    my $mcount;
    foreach my $mo ( @months ) {
	print qq{<input type="checkbox" name="M:$mo" value="1">$months{$mo} \n};
	$mcount++;
	if ( $mcount == 5 ) { print qq{<br>\n}; }
    }
    print qq{</td></tr>\n};

    print qq{<tr><td colspan="2"><hr></td></tr>\n};

    # Select Homerooms
    print qq{<tr><td class="bra">$lex{Select} $lex{Homerooms}</td>};
    print qq{<td class="la">\n};
    foreach my $hr ( sort {$a <=> $b} @homerooms ) {
	print qq{<input type="checkbox" name="H:$hr" value="1" $checkHR>$hr \n};
    }
    print qq{</td></tr>\n};

    # Select Course Grades
    if ( @grades ) { # we have course grades
	print qq{<tr><td class="bra"><span style="font-weight:normal;">$lex{or}</span> };
	print qq{$lex{Select} $lex{Course} $lex{Grade}</td>};
	print qq{<td class="la">\n};
	foreach my $gr ( sort {$a <=> $b} @grades ) {
	    print qq{<input type="checkbox" name="G:$gr" value="1" $checkGR>$gr \n};
	}
	print qq{</td></tr>\n};
    }

    print qq{<tr><td colspan="2"><hr></td></tr>\n};


    # Override Attendance Entry Method
    print qq{<tr><td class="bra">$lex{Override}<br>$lex{Attendance} $lex{Method}</td>};
    print qq{<td class="la"><select name="attmethodoverride"><option value=""></option>};
    print qq{<option value="homeroom">$lex{Homeroom}</option>\n}; 
    print qq{<option value="subject">$lex{Subject}</option>\n};
    print qq{</select></td></tr>\n};

    # Override periods per day
    print qq{<tr><td class="bra">$lex{Override}<br>$lex{'Periods per Day'}</td>};
    print qq{<td class="la"><select name="ppdoverride"><option value=""></option>\n};
    for my $i ( 1..8) { print qq{<option>$i</option>}; }
    print qq{</select></td></tr>\n};

    # Override Days Open
    print qq{<tr><td class="bra">$lex{Override}<br>$lex{'Days Open'}</td>};
    print qq{<td><input type="text" name="overridedaysopen" size="3"></td></tr>\n};
    
    # Skip Homeroom Students 1
    print qq{<tr><td class="bra">$lex{Skip} $lex{Homeroom} $lex{Students} 1</td>};
    print qq{<td class="la"><select name="skiphomeroom1"><option value=""></option>\n}; 
    foreach my $hr ( sort {$a <=> $b} @homerooms ) {
	print qq{<option>$hr</option>\n};
    }
    print qq{</select></td></tr>\n};

    # Skip Homeroom Students 2
    print qq{<tr><td class="bra">$lex{Skip} $lex{Homeroom} $lex{Students} 2</td>};
    print qq{<td class="la"><select name="skiphomeroom2"><option value=""></option>\n}; 
    foreach my $hr ( sort {$a <=> $b} @homerooms ) {
	print qq{<option>$hr</option>\n};
    }
    print qq{</select></td></tr>\n};


    # Show Withdrawn Students
    print qq{<tr><td class="bra">$lex{Show} $lex{Withdrawn}</td>};
    print qq{<td class="la"><input type="checkbox" name="showwithdrawn" value="1"></td></tr>\n}; 

    print qq{<tr><td colspan="2"><hr></td></tr>\n};
    
    # Continue
    print qq{<tr><td></td><td class="la"><input type="submit" value="$lex{Continue}">\n};
    print qq{</td></tr>\n};


    print qq{</table></form>\n};
    print qq{</body></html>\n};

    exit;

}


#------------
sub doReports {
#------------

    # foreach my $key ( sort keys %arr ) { print qq{K:$key V:$arr{$key}<br>\n}; }

    my (@hr, @gr, @mo ); # homerooms, grade, months
    foreach my $key ( keys %arr ) {
	my ($type,$val) = split(':', $key);
	if ( $type eq 'H' ) {
	    push @hr, $val;
	    delete $arr{$key};
	} elsif ( $type eq 'M' ) {
	    push @mo, $val;
	    delete $arr{$key};
	} elsif ( $type eq 'G' ) {
	    push @gr, $val;
	    delete $arr{$key};
	}
    } # remaining values in %arr are overrides;

    if ( not @mo and not (@gr or $hr)) {
	print qq{<h3><span style="color:red;">$lex{Error}:</span> };
	print qq{Missing Month or Grade/Homeroom</h3>\n};
	print qq{</body></html>\n};
	exit;
    }
    
    my %r = %arr;
    foreach my $month ( sort @mo ) {
	foreach my $homeroom ( @hr ) {
	    $r{month} = $month;
	    $r{homeroom} = $homeroom;
	    showReport( \%r );
	}
	
	foreach my $grade ( @gr ) {
	    $r{month} = $month;
	    $r{grade} = $grade;
	    showReport( \%r );
	}
    }

}




#-------------
sub showReport {
#-------------

    # foreach my $key ( sort keys %arr ) { print qq{K:$key V:$arr{$key}<br>\n}; }
    
    my %p = %{@_[0]};

    
#    foreach my $key ( sort keys %p ) { print qq{K:$key V:$p{$key}<br>\n}; }
#    print qq{<br>\n};
#    return;

    
    # Passed: homeroom, grade, month (yyyy-mm), showwithdrawn, attmethod, ppdoverride

    # Library for period absences.
#    eval require "$configpath/lib/libDate.pl";
#    if ( $@ ) {
#	print $lex{Error}. " $@<br>\n";
#	die $lex{Error}. " $@\n";
#    }

    # required in order to get a 'good' report.
    my $attmethodoverride = $p{attmethodoverride};
    my $ppdoverride = $p{ppdoverride};
    my $overridedaysopen = $p{overridedaysopen};
#    delete $arr{attmethodoverride};
#    delete $arr{ppdoverride};
#    delete $arr{overridedaysopen};

    # Why?
    my $skiphomeroom1 = $p{skiphomeroom1};
    my $skiphomeroom2 = $p{skiphomeroom2};
#    delete $arr{skiphomeroom1};
#    delete $arr{skiphomeroom2};


    # foreach my $key ( sort keys %arr ) { print qq{K:$key V:$arr{$key}<br>\n}; }
    # Passed values left: month, grade, homeroom
    
    # Check for missing values.
    if ( not $p{month} or ( not $p{grade} and not $p{homeroom} ) ) {
	print qq{<h3>$lex{Missing} $lex{Value}</h3>\n};
	print qq{</body></html>\n};
	exit;
    }


    # Show Month and Student Group
    my ($y,$m) = split('-',$p{month});
#    print qq{<h3>Month $p{month} / };
    print qq{<h3>$month[$m] $y / };
    if ( $p{grade} ) { print qq{ Grade $p{grade} }};
    if ( $p{homeroom} ) { print qq{ Homeroom $p{homeroom} }};
    print qq{</h3>\n};


    
    my $studtable = 'student';
    if ( $p{showwithdrawn} ) {
	$studtable = 'studentall';
    }

    # Get the group, default to grade.
    my $homeroomteacher;
    my $groupvalue = $p{grade};
    my $grouptype = 'grade';
    
    if ( not $p{grade} ) {
	$groupvalue = $p{homeroom};
	$grouptype = 'homeroom';

	# Get Homeroom teacher userid
	my $sth = $dbh->prepare("select userid from staff_multi where 
          field_name = 'homeroom' and field_value = ?");
	$sth->execute( $groupvalue );
	if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	$homeroomteacher = $sth->fetchrow;
	if ( not $homeroomteacher ) {
	    print qq{<h3>$lex{Homeroom} $lex{Teacher} $lex{'Not Found'}</h3>\n};
	}

    } else { # get first homeroom teacher for that grade

	my $sth = $dbh->prepare("select userid from staff_multi where field_name = 'grade' 
           and field_value = ?");
	$sth->execute( $groupvalue );
	if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my @teachers;
	while ( my $userid = $sth->fetchrow ) {
	    push @teachers, $userid;
	}

	$homeroomteacher = $teachers[0]; # first element.

    }

    
    # Get the Days Open in the month and also Days Closed (to indicate school closed). 
    
    # Get Separate Year and Month vals for query below.
    my ($year,$month) = split('-', $p{month});
    
    my %daysclosed;
    my $daysclosed; # scalar to count days closed
    my $sth = $dbh->prepare("select date, dayfraction from dates where 
      month(date) = $month and year(date) = $year"); 
    $sth->execute;
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }

    # currently the fraction field value will only be 0 or 1. 1
    # indicates closed all day for all grades/homerooms. End of
    # story. However, a 0 value indicates that there are grades
    # closed. And the record would not exist if there weren't some
    # grades closed for some periods of the day. So only a 1 is
    # significant since we use pclosed hash for periods closed by
    # grade and/or homeroom.

    
    while ( my ($dt, $fraction ) = $sth->fetchrow ) { 
	my ($y,$m,$d) = split('-',$dt);
	$d =~ s/^0//; # strip leading zeros.
	$daysclosed{$d} = $fraction; # zero or 1. A zero indicates grades/periods closed; not all day for all kids
	$daysclosed += $fraction;
    }
    # foreach my $key ( sort keys %daysclosed ) { print qq{K:$key V:$daysclosed{$key}<br>\n}; }

    
    # Add to days closed for first month if not at the start of the month.
    my ($sy, $sm, $sd) = split('-', $schoolstart); # schoolstart is global var from config.
    if ( $sy == $year and $sm == $month ) { # starting year and month is current one.
	# Add to days closed if we don't start at first of the month.
	my $firstjd = julian_day( $year, $month, '1');
	my $julianbase = $firstjd - 1;
	for my $d (1.. $sd - 1) { # loop through these other days, mark as closed
	    my $jd = $julianbase + $d;
	    my $dow = day_of_week( $jd );
	    if ( $dow == 0 or $dow == 6 ) {
		# nothing
	    } else { # mark as closed.
		$daysclosed{$d} = '1.00';
	    }
	}
    }


    # Get the number of days in the month. Set $lastday value
    my $nextmonth = $month +1;
    my $nextyear = $year;
    if ( $nextmonth > 12 ) {
	$nextmonth = 1;
	$nextyear++;
    }
    my $nextfirstdayjd = julian_day( $nextyear, $nextmonth, '1');
    my $lastday;
    if ( $currjd < ( $nextfirstdayjd - 1 ) ) {
	my @temp = inverse_julian_day( $currjd );
	$lastday = $temp[2];
    } else {
	my @temp  = inverse_julian_day( $nextfirstdayjd - 1 );
	$lastday = $temp[2];
    }

    
    my $monthstartjd = julian_day($year, $month, '1');
    my $monthendjd = julian_day($year, $month, $lastday);


    # Get the type of attendance done (homeroom or subject).
    my %teacherattendance;
    my %currterm; # structure to hold term based on grade and and dom (day of month)
    my @terms; # the terms for this month;
    my @grades; # the grades of this group of students.


    # populate @grades from student
    if ( $grouptype eq 'homeroom' ) {
	my $sth2 = $dbh->prepare("select distinct grade from student where homeroom = ?");
	$sth2->execute( $groupvalue );
	if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	while ( my $gr = $sth2->fetchrow ) {
	    push @grades, $gr;
	}
    } else { # only a single grade
	push @grades, $groupvalue;
    }


    my %pclosed; # pclosed{ day }{ grade/homeroom }{ period }
    
    # Using $year and $month find records from dates_periods for this month (periods closed);
    my $sth = $dbh->prepare("select * from dates_periods where month(date) = ? and year(date) = ?");
    $sth->execute( $month,$year );
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $ref = $sth->fetchrow_hashref ) {
	my %r = %$ref; # date, grades, period
	my ($y,$m,$d) = split('-',$r{date});
	$d =~ s/^0//; # strip any leading zero.
	my $cref = parseGradesPeriod( $r{date}, $dbh);
	%cl = %$cref; # periods closed for this date cl{grade}{period} = 1
#	foreach my $gr ( keys %cl ) {
#	    foreach my $period ( keys %{ $cl{$gr} }) {
#		print "GR:$grade Per:$period<br>\n";
#	    }
#	}
	
	foreach my $gr ( @grades ) { # in this homeroom
	    foreach my $per ( sort keys %{ $cl{$gr} } ) { # if we have a value.
		$pclosed{ $d }{ $gr }{$per} = 1;
#		print "Closed Date:$d GR:$gr Period:$per<br>\n";
	    }
	}
    }
    # we now have %pclosed{day}{grade}{period} = 1; # day is day of the month 1..(31)?

    # Test %pclosed;
=head    
    foreach my $day ( sort keys %pclosed ) {
	foreach my $grade ( sort keys %{ $pclosed{$day} } ) {
	    foreach my $period ( sort keys %{ $pclosed{$day}{$grade} } ) {
		print qq{Day:$day Grade:$grade Period:$period<br>\n};
	    }
	}
    }
=cut

    
    
    # Add Homerooms Closed system ( WAS: NSD (Non-School Days) if we have a K or PK grade)
    my $homeroomclosedflag; # was nsdflag
    #foreach my $gr (keys %g_AttendanceEntryMethod ) { # alternate approach
    foreach my $gr ( @grades ) {
#	print "Grade:$gr<br>\n";
	if ( $g_AttendanceEntryMethod{$gr} eq 'homeroom' ){
	    $homeroomclosedflag = 1;
	    last; # we only need one grade to set flag.
	}
    }

    my %homeroomclosed; # was my %nonschoolday;
    
    # Clean Up Hash (from previous loops)
    foreach my $key ( keys %homeroomclosed ) {  # clean just in case.
	foreach my $date ( %{ $homeroomclosed{$key}} ) {
	    delete $homeroomclosed{$key}{$date};
	}
	delete $homeroomclosed{$key};
    }

    # Populate
    if ( $homeroomclosedflag ) { # we have to parse the dates in the month for those grades.
	my $sth = $dbh->prepare("select * from dates_homeroom
          where month(date) = ? and year(date) = ?");
	$sth->execute( $month,$year );
	if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	while ( my $ref = $sth->fetchrow_hashref ) {
	    my %r = %$ref;
	    my ($y,$m,$d) = split('-',$r{date});
	    $d =~ s/^0//; # strip any leading zero.
	    
	    $homeroomclosed{$d}{ $r{homeroom} }{ $r{period} } = 1;
	}
    }
    
=head	
        # Test
	foreach my $day ( sort keys %homeroomclosed  ) {
	    foreach my $hroom ( sort keys %{ $homeroomclosed{$day}} ) {
		foreach my $period ( keys %{ $homeroomclosed{$day}{$hroom} } ) {
		    print qq{DAY:$day HR:$hroom  Period:$period<br>\n};
		}
	    }
	}
=cut

	# I don't think we add the homeclosed values into the
	# daysclosed hash. They are separate things. daysclosed should
	# only be for full days closed. Grades and Homeroom periods
	# closed are more complex and can vary all over the map.

	# Thus the section below is commented out.
	
=head	
	if ( $grouptype eq 'homeroom' ) {
	    my $hroom = $groupvalue;
	    foreach my $day ( sort keys %homeroomclosed ) {

		if ( $daysclosed{$d} < 1 ) { # add it in, if not global period closure
		    my $closedcount;
		    foreach my $period ( keys %{ $homeroomclosed{$day}{$hroom} } ) {
			if ( $pclosed{$day}{ $grades[0] }{$period} ) { # error; redundant;
			    print qq{<div style="color:red;font-weight:bold;">};
			    print qq{Error: Extra record for Month Day $day when already closed };
			    print qq{period $period - homeroom $hroom</div>\n};
			    next;
			}
			$closedcount++;
		    }

		    if ( $closedcount ) { # if we have some periods closed today for this homeroom
			
			# Get the grade(s) for this homeroom, then the PPD for finding fraction of day closed
			my $sth = $dbh->prepare("select distinct grade from student where homeroom = ?");
			$sth->execute( $hroom );
			if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
			my ($currppd, $prevppd, $chosenppd );
			my %homeroomppd;
			while ( my $gr = $sth->fetchrow ) {
			    $homeroomppd{ $gr } = $g_ppd{$gr};
			    $prevppd = $currppd;
			    $currppd = $g_ppd{$gr};
			    if ( $prevppd and $currppd != $prevppd ) { # Houston, we have a problem!
				print qq{<h3>Error: Homeroom $hroom has 2 different numbers of attendance periods };
				print qq{a day. Grade $gr has $currppd, while another grade is $prevppd.</h3>\n};
			    } else {
				$chosenppd  = $currppd;
			    }
			}
	    
			my $fraction = $closedcount / $chosenppd;
			print qq{Day:$day Fraction:$fraction Closed:daysclosed{$d} };
			print qq{HR:$hroom PPD:$chosenppd<br>\n};
		    
			$daysclosed += $fraction;
			$daysclosed{$d} += $fraction;
			if ( $daysclosed{$d} > 1 ) { $daysclosed{$d} = 1; }
		    } # end of closed count; 
		} # daysclosed; not closed all day anyway
	    } # day loop in the hash
	} # if a homeroom, rather than a grade.
	
    } # end of homeroomclosedflag;

# Check %daysclosed
#    foreach my $key ( sort {$a <=> $b } keys %daysclosed ) {
#	print qq{DAY:$key V:$daysclosed{$key}<br>\n};
#    }

=cut
	

    # Set Attendance Entry Method if not override.
    my $attmethod;
    if ( not $attmethodoverride ) {
	$attmethod = $g_AttendanceEntryMethod{ $grades[0] };
    } else {
	$attmethod = $attmethodoverride;
    }

    print qq{<h4>$lex{Attendance} $lex{Method}: $attmethod</h4>\n};



    # Now find matching tracks for grade(s).
    my @tracks;
    foreach my $gr ( @grades ) {
	push @tracks, $g_MTrackTermType{$gr};
    }


    my ( %tempterm ); # multiple dimensions;  $currterm{grade}{dom} = term; 
    # tempterm holds start:end pair instead of dom (day of month)
    
    # Loop through all terms of all tracks and get start/end dates, and populate %currterm;
    foreach my $gr ( @grades ) {
	my $trk = $g_MTrackTermType{$gr};
	my %temp = %{$g_MTrackTerm{$trk}};
	foreach my $term ( sort keys %temp ) {
	    my $start = $temp{$term}{start};
	    my $end = $temp{$term}{end};

	    # Check using monthstartjd, monthendjd;
	    my $startjd = julian_day( split('-', $start));
	    my $endjd = julian_day( split('-', $end));
	    if ( $startjd < $monthstartjd and $endjd > $monthendjd ) { # term straddles this month
		$tempterm{$gr}{"1:$lastday"} = $term;
		
	    } elsif ( $startjd >= $monthstartjd and $startjd <= $monthendjd ) { # term starts in this month sometime.
		my ( $sy, $sm, $sd ) = split('-', $start);
		$tempterm{$gr}{"$sd:$lastday"} = $term;

	    } elsif ( $endjd >= $monthstartjd and $endjd <= $monthendjd ) {  # term ends in this month.
		my ( $ey, $em, $ed ) = split('-', $end);
		$tempterm{$gr}{"1:$ed"} = $term;
	    }
	}
    }

    # populate the %currterm hash, so we know what term it is for any grade on any day this month.
    foreach my $gr ( keys %tempterm ) {
	foreach my $pair ( keys %{ $tempterm{$gr}} ) {
	    my ( $start, $end ) = split(':', $pair);
	    $start =~ s/^0//;  # strip any leading zeros
	    $end =~ s/^0//;
	    for my $day ( $start..$end ) {
		$currterm{$gr}{$day} = $tempterm{$gr}{$pair};
	    }
	}
    }  

=head  # Testing

	foreach my $gr ( keys %tempterm ) {
	    my %temp = %{$tempterm{$gr}};
	    foreach my $day ( sort {$a <=> $b} keys %temp ) {
		print qq{TEMP Grade|$gr Day|$day Term: $temp{$day}<br>\n};
	    }
	}  

    # Test 
    foreach my $gr ( keys %currterm ) {
	my %temp = %{$currterm{$gr}};
	foreach my $day ( sort {$a <=> $b} keys %temp ) {
	    print qq{Grade|$gr Day|$day Term: $temp{$day}<br>\n};
	}
    }  
=cut

    # Populate %teachername hash
    my %teachername;
    my $sth = $dbh->prepare("select lastname, firstname, userid from staff");
    $sth->execute;
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my ($lastname, $firstname, $userid) = $sth->fetchrow ) {
	$teachername{$userid} = "$firstname $lastname";
    }
    # foreach my $key ( sort keys %teachername ) { print qq{K:$key V:$teachername{$key}<br>\n}; }

    

    # Get their Attendance Entry for the Month; populate teacherattendance
    my $sth = $dbh->prepare("select * from tattend where month(attdate) = $month and year(attdate) = $year"); 
    $sth->execute;
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }

    # prepare to get homeroom for a teacher.
    # my $sth1 = $dbh->prepare("select field_value from staff_multi where field_name = 'homeroom' and userid = ?");

    # Get all teacher attendance for the month
    while ( my $ref = $sth->fetchrow_hashref ) {
	my ($y,$m,$day) = split('-', $ref->{attdate});
	$day =~ s/^0//; # strip leading zero
	my (@per, @subj);

	my $userid = $ref->{userid};
	my $period = $ref->{periods};
	if ($period =~ m/,/ ) { # if period contains commas, then we have to split
	    print qq{<div>ERROR: Teacher Period contains commas. Contact Les Richardson!</div>\n};
	    # @per = split(',',$period);
	} else {
	    push @per, $period;
	}

	my $subject = $ref->{subjects};
	if ( $subject =~ m/,/ ) { # multiple subjects
	    print qq{<h3>Warning: multiple subjects for User:$userid on $y-$m-$day: $subject</h3>\n};
	    my @temp = split(',',$subject); 
	    $subject = $temp[0]; # throw away any trailing subjects.
	    
	} elsif ( not $subject ) { # look up homeroom and populate with that instead
	    # Wrong: It could be any teacher. 
	    # $sth1->execute($userid);
	    # if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	    # my $hr = $sth1->fetchrow;
	    #if ( not $hr) { 
		print qq{<h4>$lex{Error}: Missing Subject/Homeroom field for userid:$userid Day:$day</h4>\n};
	    #} else { # populate the subject field;
	    #$subject = 'HR:'.$hr;
	    # }
	}

	foreach my $per ( @per ) {  # @per will now only have a single value; we only store a single period per rec
	    $teacherattendance{$day}{$per}{$subject} = $userid;  # day, period, subject should be unique.
	    # even if we have backed subjects and/or more than one period per day.
	}

    } # end of teacher attendance loop

=head
    foreach my $day ( sort keys %teacherattendance ) {
	foreach my $period ( sort keys %{ $teacherattendance{$day} } ) {
	    foreach my $subject ( sort keys %{ $teacherattendance{$day}{$period} } ) {
		print "Day:$day Period:$period Subj:$subject<br>\n";
	    }
	}
    }
=cut
    
  
    # Print Group Name
    if ( $grouptype eq 'grade' ) {
	print qq{<h3>$lex{Grade} $groupvalue</h3>\n};

    } else {
	print qq{<h3>$lex{Homeroom} $groupvalue - $teachername{$homeroomteacher} };
	print qq{($homeroomteacher)</h3>\n};
    }


    # Find DOW of first of month
    my %weekend; # stores weekend days in month
    my $firstsunday;
    my $firstjd = julian_day( $year, $month, '1');
    my $julianbase = $firstjd - 1;

    my $daysopen; # first just gross days; take away closed days later
    for my $d ( 1..$lastday ) {
	my $jd = $julianbase + $d;
	my $dow = day_of_week( $jd );
	if ( $dow == 0 or $dow == 6 ) {
	    $weekend{$d} = $dow;
	} else { # open
	    $daysopen++;
	    $daysopen = $daysopen - $daysclosed{$d};
	}
    }


    # Adjustment value if overridedaysopen is set. We assume that the
    # override value is the real days open value (which has considered
    # days including days the school is fully or partially
    # closed. This is the daysopen value above.  

    print qq{<div style="padding-bottom:0.5em;">Days Open (to date): $daysopen</div>\n};

    my $overrideDO; 
    if ( $overridedaysopen ) { 
	$overrideDO = $daysopen - $overridedaysopen;  # a positive value since days open will be larger.  

	if ( overrideDO < 0 ) { 
	    print qq{<h3>Error: The days open, $daysopen, (including days marked closed), <br>\n};
	    print qq{is smaller than the override days.</h3>\n};
	    print qq{</body></html>\n};
	    exit;
	}
    }

    if ( $overrideDO ) {
	print qq{<div>Days Open Override factor: $overrideDO. Days removed from days open</div>\n};
    }

=head
    print qq{Year:$year Month:$month<br>\n};
    print qq{Last Day:$lastday<br>\n};
    print qq{Closed: $daysclosed<br>\n};
    exit;
=cut


    my ($ppd, $currppd, $oldppd );
    if ( $ppdoverride ) {
	$ppd = $ppdoverride; 
    } else { # no override
	if ( $#grades == 0 ) { # only 1 grade;
	    $gr = $grades[0];
	    $ppd = $g_ppd{$gr};
	    if ( not $ppd or $currppd != $oldppd  ) {
		print qq{<h3>Periods per Day Error for Grade:$gr</h3>\n};
		print qq{</body></html>\n};
		exit;
	    }
	    
	} else { # more than 1 grade; check all the same value
	    my $first = 1;
	    foreach my $gr ( @grades ) {
		if ( $first ) { # just set currppd
		    $ppd = $currppd = $g_ppd{$gr};
		    $first = 0;
		    next;
		}
		$oldppd = $currppd;
		$ppd = $currppd = $g_ppd{$gr};

		if ( not $ppd or $currppd != $oldppd  ) {
		    print qq{<h3>Periods per Day Error for Grade:$gr</h3>\n};
		    print qq{</body></html>\n};
		    exit;
		}
	    }
	}
    } # end of no override
#    print qq{PPD:$ppd<br>\n};


    
# Not Needed, I think!
=head    
    if ( $homeroomclosedflag ) {
	# add in periods closed from homeroomclosed hash for PK,K periods closed.
	foreach my $hroom ( sort keys %homeroomclosed  ) {
	    my $hrsubject = 'HR:'.$hroom;
	    foreach my $date ( sort keys %{ $homeroomclosed{$hroom}} ) {
		my ($y,$m,$day) = split('-', $date);
		$day =~ s/^0//; # strip leading zero.
		foreach my $period ( keys %{ $homeroomclosed{$hroom}{$date} } ) {
		    $pclosed{$day}{$hrsubject}{$period} = 1;
		}
	    }
	}
    }
=cut
	
    
=head
    # Test pclosed hash values
    foreach my $day ( sort keys %pclosed ) {
	foreach my $grade ( sort keys %{ $pclosed{$day} } ) {
	    foreach my $period ( sort keys %{ $pclosed{$day}{$grade} } ) {
		print qq{Day:$day Grade:$grade Period:$period<br>\n};
	    } }
    }
=cut
# end of PERIODS CLOSED loading.


    # Now we're ready to send some OUTPUT!
        
    # Map Periods to some text...
    my %map;
    if ( $ppd == 2 ) { # am/pm
	$map{1} = 'AM';
	$map{2} = 'PM';
    } else {
	for (1..$ppd) {
	    $map{$_} = "P$_";
	}
    }

   
    
    print qq{<table cellpadding="1" cellspacing="0" border="1" style="margin-bottom:2em;">\n};
    print qq{<caption style="font-weight:bold;font-size:120%;text-align:left;">};
    print qq{$lex{Hover}=$lex{View}, $lex{Click}=$lex{Edit}};
    print qq{<span style="padding:2em;font-size:100%;">P=$lex{Present}, };
    print qq{A=$lex{Absent}, NE=$lex{'No Entry'}</span></caption>\n\n};

    # Heading;
    # Both needed for pclosed by grade; homeroom closed by homeroom.
    my $homeroom = $p{homeroom};
    my $grade = $grades[0];
    
    print qq{<tr><th></th><th class="dr"></th>};
    foreach my $day ( 1..$lastday ) {
	if ( exists $weekend{$day} ) { next; }
	if ( $daysclosed{$day} >0.99 ) { # full day closed
	    print qq{<th>$s_month[$month] $day</th>};
	} else { # header for all periods
	    print qq{<th colspan="$ppd" class="dr">$s_month[$month] $day</th>};
	}
    }
    print qq{<th></th><th></th></tr>\n};

    print qq{<tr><th>$lex{Student}</th><th class="dr"></th>};
    foreach my $day ( 1..$lastday ) {
	if ( exists $weekend{$day} ) { next; }
	if ( $daysclosed{$day} >0.99 ) { # full day closed
	    print qq{<td style="background-color:$closedcolor;"></td>\n};
	} else { # print periods
	    for my $per ( 1..$ppd ) {

		my $fmt;
		if ( $per == $ppd ) { $fmt = qq{class="dr"}; }

		# closed this period.
		if ( $pclosed{$day}{$grade}{$per} or $homeroomclosed{$day}{$homeroom}{$per}) { 
		    print qq{<td style="background-color:$closedcolor;" $fmt>$map{$per}</td>};
		} else { # OR not closed
		    print qq{<td $fmt>$map{$per}</td>};
		}
		print qq{\n}; # separate lines in source view.
	    }
	}
    }
    print qq{<td class="bcn">$lex{Enrolled}</td><td class="bcn">$lex{Attended}</td></tr>\n\n};
    # end of heading.
    
    
    # Get Current Student Group and Names
    my (%students, %studname, %studgrade, %studroom );
    my $sth = $dbh->prepare("select lastname, firstname,studnum, grade, homeroom from $studtable 
      where $grouptype = ? order by lastname, firstname");
    $sth->execute( $groupvalue );
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my ($lastname, $firstname, $studnum, $grade, $homeroom ) = $sth->fetchrow ) {

#	print qq{$lastname $firstname ($studnum)<br>\n};
	if ( $homeroom and ( $homeroom eq $skiphomeroom1 or $homeroom eq $skiphomeroom2 )) { next; }

	$students{$studnum} = "$lastname$firstname$studnum"; # store sortkey in value;
	$studname{$studnum} = "<b>$lastname</b>, $firstname";
	$studroom{$studnum} = $homeroom;
	$studgrade{$studnum} = $grade;
    }

    # Check enrollments and add/remove students for month of interest.

    # The current %students hash has Current Students, so we have to
    # check for any that were added/removed from current date, back to
    # the start of this month. If they were students at any time
    # during this month, they are added/retained.

    my $cmonth = $p{month}. '-01';
    my $sth1 = $dbh->prepare("select * from transfer where 
      to_days(date) >= to_days('$cmonth') order by date desc");
    $sth1->execute;
    if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; }

    # Setup query to get grade, homeroom
    my $sth2 = $dbh->prepare("select lastname, firstname, grade,homeroom from studentall 
      where studnum = ?");

    while ( my $ref = $sth1->fetchrow_hashref ) {

	my %tr = %$ref;
	my $studnum = $tr{studnum};
	
	$sth2->execute( $studnum );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my ($lastname, $firstname, $grade,$homeroom) = $sth2->fetchrow;

	my $monthmode;  # means that this enrollment record is in the month of interest
	my ($y,$m,$d) = split('-', $tr{date});
	if ( $y == $year and $m == $month ) { $monthmode = 1; }
	
	
	# Change Enrollment Numbers, and %students
	if ( $tr{type} ne 'withdraw' ) {
	    # then was an enrol after this month; thus not enrolled in this month.
	    # Remove, if not current month
	    if ( not $monthmode ) {
		delete $students{ $studnum };
	    }

	} else { # withdraw, so they must have been enrolled. Add them.
	    if ( not $students{$studnum} ) { # put them in IF
		if ( ($grouptype eq 'grade' and $grade == $groupvalue ) or
		     ($grouptype eq 'homeroom' and $homeroom eq $groupvalue )) { # add 'em
		    $students{ $tr{studnum} } = "$lastname$firstname$tr{studnum}";
		    $studroom{ $tr{studnum} } = $homeroom;
		    $studgrade{ $tr{studnum} } = $grade;
		}
	    }
	}

    }
    # end of checking enrollments

    # Check if we have all the students we want....
#    foreach my $key ( sort keys %students ) {
# 	print qq{SN:$key NAME:$students{$key}<br>\n};
#    }
    

    # Now Get Coursedescriptions, teachers

    # Get All Course Descriptions and Teachers
    my (%coursename, %teachercourse);
    my $sth = $dbh->prepare("select description, teacher, subjsec from subject");
      # where subjsec = ? ");
      # foreach my $subjsec ( keys %{ $termcourses{$currterm} } ) {
    $sth->execute;
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my ( $desc, $userid, $subjsec ) = $sth->fetchrow ) {
	$coursename{$subjsec} = $desc;
	$teachercourse{$subjsec} = $userid; # get teacher userid from the course (subjsec)
    }
    # foreach my $key ( sort keys %coursename ) { print qq{K:$key V:$coursename{$key}<br>\n}; }
    # foreach my $key ( sort keys %teachercourse ) { print qq{K:$key V:$teachercourse{$key}<br>\n}; }


#    TEST
#    foreach my $term ( sort keys %termcourses ) {
#	foreach my $subjsec ( sort keys %{ $termcourses{$term} } ) {
#	    print qq{Term:$term  Subjsec:$subjsec };
#	}
#    }

    

    # Create a hash for day in cycle for this month.
    my %dayincycle;
    for my $d ( 1..$lastday ) {
	my $dic = findDayInCycle( "$year-$month-$d", $dbh );
	# print qq{Day of Month:$d  Cycle Day:$dic<br>\n};
	$dayincycle{$d} = $dic;
    }

    # Missing Attendance - show this on bottom row
    my %missingatt; # missing attendance  $missingatt{$day};


    # SETUP for STUDENT LOOP
    # get attendance values
    my $sth1 = $dbh->prepare("select * from attend where month(absdate) = $month 
      and year(absdate) = $year and studentid = ?");

    # wd status check for withdrawals this month.
    # $year and $month defined at top of the script.
    my $sth2 = $dbh->prepare("select count(*) from transfer where studnum = ? and 
       type = 'withdraw' and month(date) = $month and year(date) = $year");

    # get enrollment changes (ie. transfers)
    my $sth3 = $dbh->prepare("select date, type from transfer where month(date) = $month and 
      year(date) = $year and studnum = ? order by date");

    # Get Student Course Enrollments
    my $sth4 = $dbh->prepare("select subjcode from eval where studnum = ? and term = ?");

    # Get student timetable values
    my $sth5 = $dbh->prepare("select day,period from schedat where subjsec = ? and term = ?");

    
    
    # STUDENT LOOP
    my $studcount; # student count

    my ($totaldaysenrolled, $totaldaysattended);

    
    my %sorted = reverse %students;

    foreach my $key ( sort keys %sorted ) {
	my $studnum = $sorted{$key};

	my $name = $studname{ $studnum };
	my $grade = $studgrade{ $studnum };
	# needed to find current term, hence course enrollments, timetable
	my $homeroom = $studroom{$studnum};

	if ( not $name ) {
	    my $sth1 = $dbh->prepare("select lastname, firstname from studentwd where studnum = ?");
	    $sth1->execute( $studnum );
	    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	    ($lastname, $firstname) = $sth1->fetchrow;
	    $name = "<b>$lastname</b>, $firstname";
	}


	my %trms; # get current terms for this student;
	foreach my $d ( 1..$lastday ) {
	    my $t = $currterm{$grade}{$d};
	    $trms{$t} = 1;
	}


	my $statsflag = 1;
	# print the attendance stats in final column IF all teacher attendance entries done.

	my %studenttimetable;
	if ( $attmethod eq 'subject' ) { # get student timetable:  term/day/period/ = subjsec;

	    # First get enrolled courses, then get timetable values for those courses.
	    foreach my $trm (sort keys %trms) { # loop over all terms this month for this student
		# Get enrolled courses
		$sth4->execute($studnum, $trm);
		if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
		while ( my $subjsec = $sth4->fetchrow ) {
		    # Get day/periods
		    $sth5->execute($subjsec, $trm);
		    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
		    while ( my ($day,$period) = $sth5->fetchrow ) {
			$studenttimetable{$trm}{$day}{$period} = $subjsec;
		    }
		}
	    }
	} # end of getting student timetable, for course attendance.

#       Checking data structure of studenttimetable.
=head
	print qq{<div>Student:$studnum</div>\n};
	foreach my $t ( sort keys %studenttimetable ) {
	    foreach my $d ( sort keys %{ $studenttimetable{$t} } ) {
		foreach my $p ( sort keys %{ $studenttimetable{$t}{$d} } ) {
		    print qq{ Term:$t Day:$d Period:$p Course:$studenttimetable{$t}{$d}{$p}<br>\n}; 
		}
	    }
	}
=cut

	# Get Attendance Data
	my %att;
	$sth1->execute( $studnum );
	if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    
	while ( my $r = $sth1->fetchrow_hashref ) {
	    my ($y,$m,$day) = split('-', $r->{absdate} );
	    $day =~ s/^0//;
	    my $period = $r->{period};
	
	    $att{$day}{$period}{'reason'} = $r->{reason};
	    $att{$day}{$period}{'subjsec'} = $r->{subjsec};
	    $att{$day}{$period}{'late'} = $r->{late};
	    $att{$day}{$period}{'id'} = $r->{attid};
	}


	# Get wd status: check for a withdrawal record this month.
	my $wdflag;
	$sth2->execute( $studnum );
	if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $ecount = $sth2->fetchrow;
	if ( $ecount ) { 
	    $wdflag = 1; 
#	    print qq{WD - SN:$studnum<br>\n};
	} # flag set (==1) is withdrawn;

	
	# Get Enrollment Data for this month. We don't have to get
	# later dates since this is already done to see if they are
	# current students or not. Earlier records are checked below.
	
	my %enrol;
	$sth3->execute( $studnum );
	if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    	while ( my ($date, $type) = $sth3->fetchrow ) {
	    my ($y,$m,$day) = split('-', $date );
	    $day =~ s/^0//; # strip leading zero
	    if ( exists $enrol{$day} ) { 
		print qq{<h3>Enrollment Error: $name ($studnum) - $date</h3>\n};
	    }
	    $enrol{$day} = $type;
	}

#	print qq{$studnum \n};
#	foreach my $key ( sort keys %enrol ) { print qq{K:$key V:$enrol{$key}\n}; }
#	print qq{<br>\n};

	
	# Set Initial Enrollment Status value ($estatus)
	my $estatus;
	if ( not %enrol ) { # no enrollment changes this month, were they enrolled before?
	    # read the previous record to see if a withdraw
	    my $startdate = "$year-$month-01";
	    my $sth = $dbh->prepare("select date, type from transfer where 
               to_days(date) < to_days('$startdate') and studnum = ? order by date desc");
	    $sth->execute($studnum); # get the record just before this month to find enrollment status.
	    my ($date, $type) = $sth->fetchrow;
	    if ( $type eq 'withdraw' ) { #
		$estatus = 0; $wdflag = 1; 
	    } else { 
		$estatus = 1; $wdflag = 0;
	    }
	    
	} else { # we have enrollment changes.
	    my @tmp = sort {$a <=> $b} keys %enrol;
	    my $etype = $enrol{$tmp[0]}; # first enrollment change value in the month;
	    if ( $etype eq 'withdraw' ) {
		$estatus = 1; $wdflag = 0; # must have been enrolled at start of the month.
		# Note: even if withdrawn on the 1st, he/she would have been there for that day.
		# If type is enrol, then she/he must have not been enrolled at start of the month.
	    } else { # first record NOT a withdraw, must be ENROL.
		$estatus = 0; # $wdflag = 1;
	    }
	}

#	print qq{Name:$name Estatus:$estatus<br>\n};
	
	my $wd;
	if ( $wdflag ) {
	    $wd = qq{<span style="color:red;font-weight:bold;">$lex{WD}</span>};
	}

	$studcount++;
	print qq{<tr><td class="la">$name ($studnum) $wd</td>};
	print qq{<td class="dr">Gr:$grade<br>Hr:$homeroom</td>\n};

	my ( $periodspresent, $daysenrolled, $attendclosure ); 
	#attendclosure: student present, but school closed for part of day; an adjustment factor.

	
	# DAY LOOP - loop through the month
	foreach my $day ( 1..$lastday ) {
	    if ( exists $weekend{$day} ) { next; }

	    if ( $daysclosed{$day} > 0.99 ) { # completely closed

		# also watch for enrollment changes ($estatus)
		if ( $enrol{$day} eq 'withdraw' ) { # status change
		    $estatus = 0;
		}
		if ( $enrol{$day} eq 'enrol' ) { # status change
		    $estatus = 1;
		}

		print qq{<td style="background-color:$closedcolor;" class="bcn">C</td>\n};
		next;
	    } 

	    my $partclosedstyle = qq{style="background-color:$partclosedcolor;"};

	    # update enrollment status ($estatus), if necessary
	    if ( $enrol{$day} eq 'enrol' ) { # status change
		$estatus = 1;
	    }
	    if ( not $estatus ) { # not enrolled
		print qq{<td style="background-color:$notenrolledcolor;" };
		print qq{class="bcn" colspan="$ppd"></td>\n};
		next;
	    }

	    # If here, then student is enrolled;
	    $daysenrolled += (1 - $daysclosed{$day} );

	    # Note: the part of day absent cannot be greater than the
	    # part of the day open (ie. 1-daysclosed{$day})

	    if ( $daysclosed{$day} ) {
		# we have a partial day closure; full day closed is skipped above.
		
		my $temp; # find out how many periods marked absent.
		for my $per ( 1..$ppd ) {
		    my $reason = $att{$day}{$per}{'reason'};
		    if ( $reason =~ m/Absent/ ) {
			$temp++;
		    }
		}
		my $dayfractionabsent = $temp / $ppd;
		if ( $dayfractionabsent > $daysclosed{$day} ) {
		    #print qq{Too much absent! Day:$day Student:$studnum<br>\n};
		    $attendclosure += (1 - $dayfractionabsent);
		} else {
		    $attendclosure += $daysclosed{$day};
		}
	    }

	    my $dayincycle = $dayincycle{$day}; # used for course attendance
	    my $currterm = $currterm{$grade}{$day}; # grade of student, day of month

	
	    # PERIOD LOOP - loop through all periods
	    for my $per ( 1..$ppd ) {
		my $class;
		if ( $per == $ppd ) { $class = qq{class="dr"}; } # use day separator

		my ($subject, $late);

		if ( $att{$day}{$per}{'subjsec'} ) { # %att is attendance record store
		    my $subjsec = $att{$day}{$per}{'subjsec'};
		    my $desc = $coursename{$subjsec};
		    if ( not $desc ) { $desc = $subjsec; }
		    $subject = "$lex{Course}:$desc";
		}
		if ( $att{$day}{$per}{'late'} ) {
		    $late = "$lex{Late}:$att{$day}{$per}{'late'}";
		}

		my $val;
	    

		# Here is where we check that attendance has been entered by teacher.
		my $nocourseenrollment; # were they enrolled in a course in this period?
		# SUBJECT/Course Attendance Method
		if ( $attmethod eq 'subject' ) { # need to find the teacher for this period, this day.

		    # we know: $day (of month), $dayincycle, $per (period), $currterm

		    my $courseoffered = $studenttimetable{$currterm}{$dayincycle}{$per};
		    my $userid = $teacherattendance{$day}{$per}{$courseoffered};
		    
		    # Check for a day closed, student present, a spare(no course), or not done att.
		    if ( $pclosed{$day}{$grade}{$per} ) { # closed this period.
			my $coursename = $coursename{$courseoffered};
			my $teachername = $teachername{$userid};
			$val = qq{<td style="background-color:$closedcolor;" }.
			    qq{title="Course:$coursename ($courseoffered) }.
			    qq{Teacher:$teachername ($userid)" $class>}.
			    qq{C</td>};
			    
		    } elsif ( $userid ) { # a userid indicates things are done.
			my $coursename = $coursename{$courseoffered};
			my $teachername = $teachername{$userid};
			$val = qq{<td title="Course:$coursename ($courseoffered) }.
			    qq{Teacher:$teachername ($userid)" $class>P</td>};
			
		    } elsif ( not $courseoffered ) {
			
			$nocourseenrollment = 1;
			$val = qq{<td $partclosedstyle title="No course found in timetable }.
			    qq{$class Term:$currterm Per:$per Day:$dayincycle"></td>};

#			if ( $studnum == 10500 ) {
#			    print qq{<div>Student:$studnum</div>\n};
#			    foreach my $t ( sort keys %studenttimetable ) {
#				foreach my $d ( sort keys %{ $studenttimetable{$t} } ) {
#				    foreach my $p ( sort keys %{ $studenttimetable{$t}{$d} } ) {
#					print qq{ Term:$t Day:$d Period:$p Course:$studenttimetable{$t}{$d}{$p}<br>\n}; 
#				    }
#				}
#			    }
#			}

			
		    } else { # No entry done by teacher.
			my $coursename = $coursename{$courseoffered};
			my $teacheruserid = $teachercourse{$courseoffered};
			 # is userid of teacher for this course.
			my $teachername = $teachername{$teacheruserid};
			my $sname = $studname{$studnum};
			$sname =~ s/<b>|<\/b>//g;  # strip bolding.
			$missingatt{$day} .= qq{$coursename ($courseoffered) Period $per\n}.
			    qq{\t$teachername ($teacheruserid) / $sname ($studnum)\n};
			
			# print qq{Period:$per DOM:$day Student:$studname{$studnum} };
			# print qq{$studnum $coursename $teachername<br>\n};

			$val = qq{<td $partclosedstyle title="No Attendance Entry. }.
			    qq{Course: $coursename ($courseoffered) Teacher:$teachername }.
			    qq{($teacheruserid)" $class><b>NE</b></td>\n};
			$statsflag = 0; # this will cause no month end attendance percentage.

#			print qq{Course:$coursename ($courseoffered) Statsflag:$statsflag<br>\n};
		    }

#		    print qq{$studnum - Day:$day Term:$currterm Per:$per Course:$courseoffered Statsflag:$statsflag<br>\n};
		    
		} else { # HOMEROOM METHOD
		    my $hrsubject = 'HR:'.$p{homeroom};
		    # what will be in the 'subject' field of array
#		     print "<b>SUB</b>:$hrsubject <b>DOM</b>:$day <b>Period</b>:$per ";
#		     print qq{<b>Tch Attendance</b>:$teacherattendance{$day}{$per}{$hrsubject}<br>\n};
#		     print "<b>HR Closed</b>:$homeroomclosed{$day}{$homeroom}{$per}<br>\n";

		    # Both grade vals ARE defined print "Grade: $grade, Grades:", @grades, "</br>\n";
		    
		    # Closed  (both on homeroom or grade closed
		    if ( $homeroomclosed{$day}{$homeroom}{$per} or
			 $pclosed{$day}{$grade}{$per} ) { 
			$val = qq{<td style="background-color:$closedcolor;" $class }.
			    qq{title="HRoom $homeroom DOM:$day Per:$per">C</td>};
			
		    # Present
		    } elsif ( $teacherattendance{$day}{$per}{$hrsubject} ){
			$val = qq{<td $partclosedstyle $class>P</td>};

		    # Missing Attendance Entry
		    } else {
			# $missingatt{$day} = 1; # missing attendance
			$missingatt{$day} .= qq{$teachername{$homeroomteacher} }.
			    qq{($homeroomteacher)\n};

			$val = qq{<td $partclosedstyle title="No Attendance Entry:}.
			    qq{$teachername{$homeroomteacher} }.
			    qq{($homeroomteacher)" $class><b>NE</b></td>};
			$statsflag = 0;
		    }

		}
		

		if ( $reason = $att{$day}{$per}{'reason'} ) {
		    # if we have a record for that day and period.
		    
		    my $rsn = q{NA};
		    if ( $reason =~ m/Absent/ ) {
			$rsn = 'A';
			
		    } elsif ( $reason =~ m/Late/ ) {
			$rsn = 'L';
			$periodspresent++;
			# still consider them present; could add a variable and check minutes late.
		    }
		    
		    my $attid = $att{$day}{$per}{'id'};
		    $val = qq{<td title="$lex{Reason}:$reason $subject $late $lex{Period}:$per" }.
			qq{style="font-weight:bold;$partclosed" $class>}.
			qq{<a href="atted.pl?id=$attid" style="color:red;">$rsn</a></td>};

		} else { # child was present
		    if ( not $nocourseenrollment ) { # if enrolled in a course (doesn't affect homeroom)
			$periodspresent++;
		    }
		}
		
		print $val;
		
	    } # end of printing loop (each period)
	    
	    
	    # update enrollment status ($estatus), if necessary
	    if ( $enrol{$day} eq 'withdraw' ) { # status change
		$estatus = 0;
	    }

	} # end of day loop

	my $tempdayspresent = ($periodspresent / $ppd) - $attendclosure;
#	print qq{SN:$studnum Present:$periodspresent Closure:$attendclosure };
#	print qq{TEMP:$tempdayspresent PPD:$ppd<br>\n};
	
	if ( $overridedaysopen ) { 
	    $tempdayspresent = $tempdayspresent - $overrideDO;  
	    # overrideDO is difference between 'normal' days open and overridden days open
	}

	my $dayspresent = format_number( $tempdayspresent ,2,2);
	if ( $dayspresent < 0 ) { $dayspresent = 0; }
	
	# Adjust days enrolled by the same factor, even if we don't know for sure.
	if ( $overridedaysopen ) { 
	    $daysenrolled = $daysenrolled - $overrideDO;  
	}


	$totaldaysattended += $dayspresent;
	$totaldaysenrolled += $daysenrolled;
	
	my $daysenrolled = format_number( $daysenrolled, 2, 2);

	my $percentattend;
	if ( $daysenrolled != 0 ) {
	    $percentattend = format_number( $dayspresent / $daysenrolled * 100, 1);
	} else { $percentattend = '0'; }

	print qq{<td class="cn">$daysenrolled</td>\n};

	if ( $statsflag ) { 
	    print qq{<td class="cn">$dayspresent ($percentattend%)</td></tr>\n};
	} else { 
	    print qq{<td class="bcn" title="$lex{Missing} $lex{Attendance}">$lex{Error}</td></tr>\n};
	}
    
	# Empty the student timetable values
	foreach my $t ( sort keys %studenttimetable ) {
	    foreach my $d ( sort keys %{ $studenttimetable{$t} } ) {
		foreach my $p ( sort keys %{ $studenttimetable{$t}{$d} } ) {
		    # print qq{ Term:$t Day:$d Period:$p Subject:$studenttimetable{$t}{$d}{$p}<br>\n};
		    delete $studenttimetable{$t}{$d}{$p};
		}
		delete $studenttimetable{$t}{$d};
	    }
	    delete $studenttimetable{$t};
	}

    } # end of student loop
    

    # Teacher Attendance Loop
    my $currterm = -1; # start with a dud.
    my $prevterm;
    my @courses; # only for subject attendance.

    print qq{<tr><td class="bcn">Teacher Attendance Entry</td><td class="dr"></td>\n};


    foreach my $day ( 1..$lastday ) {

	if ( exists $weekend{$day} ) { next; }
	if ( $daysclosed{$day} > 0.99 ) {
	    print qq{<td style="background-color:$closedcolor;" class="bcn"></td>\n};
	    next;
	} 

	if ( $missingatt{$day} ) { 
	    print qq{<td colspan="$ppd" style="background-color:red;color:white;};
	    print qq{font-weight:bold;text-align:center;border-right-style:double;};
	    print qq{border-right-width:3px;"};
	    print qq{ title="Missing Attendance\n$missingatt{$day}">\n};
	    print qq{$lex{Error} (hover)</td>\n};

	} else { 
	    print qq{<td colspan="$ppd" style="font-weight:bold;text-align:center;};
	    print qq{border-right-style:double; border-right-width:3px;">$lex{OK}</td>\n};
	}

    } # end of teachers days loop

    my $pa = 0;
    if ( $totaldaysenrolled ) {
	$pa = format_number( 100 * $totaldaysattended / $totaldaysenrolled, 2, 2);
    }
    
    print qq{<td class="bcn">$totaldaysenrolled</td>};
    print qq{<td class="bcn">$totaldaysattended ($pa%)</td><tr>\n};
    print qq{</table>\n};

#    print qq{<table cellpadding="3" border="0" cellspacing="0">\n};
#    print qq{<tr><td class="la">$lex{'Days Open'}</td><td>$daysopen</td></tr>\n};
#    print qq{<tr><td class="la">$lex{'Days Closed'}</td><td>$daysclosed</td></tr>\n};
#    print qq{</table>\n};

    
#    print qq{</body></html>\n};

    print qq{<div style="page-break-after:always;"></div>\n};
    
    return; 

} # end of showReport



#--------------
sub findCourses {
#--------------

    # Find the courses this term for these students, passed a list of studnums, after the term to check.
    my ( $term, @students ) = @_;
    if ( not $term ) {
	print qq{<div>Missing Term for students</div>\n};
	return;
    }

    my %courses;

    my $sth = $dbh->prepare("select distinct subjcode from eval where studnum = ? and term = $term");
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }

    foreach my $studnum ( @students ) {

	$sth->execute( $studnum );
	if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	while ( my $subjsec = $sth->fetchrow ) {
	    $courses{$subjsec} = 1;
	}
    }

    return keys %courses;

}

#---------------------
sub findCourseTeachers {
#---------------------

    # Find the teachers for these courses, passed a list of studnums
    my @courses = @_;
    my @teachers;

    my $sth = $dbh->prepare("select teacher from subject where subjsec = ?");

    foreach my $subjsec ( @courses ) {
	$sth->execute( $subjsec );
	if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $userid = $sth->fetchrow;
	push @teachers, $userid;
    }

    return @teachers;

}


#---------------------
sub getStudentsInMonth {  # find all students in this month at some point.
#---------------------

    # Outline: Get current students, then backup to the END of current
    # (actually start of following) month, adding and removing
    # students from transfers
    

    my ($yrmo, $grade, $homeroom) = @_;
    my %students;

    my ($select, $selectval, $selecttype);
    if ( $grade ) {
	$select = 'where grade = ?';
	$selectval = $grade;
	$selecttype = 'grade';
	
    } elsif ( $homeroom ) {
	$select = 'where homeroom = ?';
	$selectval = $homeroom;
	$selecttype = 'homeroom';
	
    } else {
	print qq{<h3>getStudentsInMonth - $lex{Error}: Missing Grade or Homeroom</h3>\n};
	exit;
    }
    
    # Get current kids in this room
    my $sth = $dbh->prepare("select studnum from student $select");
    $sth->execute( $selectval );
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $studnum = $sth->fetchrow ) {
	$students{$studnum} = 1;
    }


    # Now run through Transfer records checking for other students in
    # this grade/room, and update %students until we reach the month
    # of interest.
    my $sth1 = $dbh->prepare("select grade,homeroom from studentall where studnum = ?");
    
    my $startdate = $yrmo. '-01';
    my $sth = $dbh->prepare("select * from transfer where to_days(date) >= to_days('$startdate') 
     order by date desc");
    $sth->execute;
    if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; }

    while ( my $ref = $sth->fetchrow_hashref ) {
	my %tr = %$ref;

	$sth1->execute( $tr{studnum} );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my ($grade,$homeroom)  = $sth2->fetchrow;

	if ( $selecttype eq 'homeroom' and $homeroom ne $selectval ) { next; }
	if ( $selecttype eq 'grade' and $homeroom ne $selectval ) { next; }

	# If here, they must be in the correct homeroom/grade group,
	if ( $tr{type} ne 'withdraw' ) { # Enrol here so we remove them, if not in the month of interest.
	    if ( $tr{date} =! m/$yrmo/ ) { # if NOT month of interest, delete them.
		
	    }
	}
    }



}
