#!/usr/bin/perl
# Copyright 2001-2008 Leslie Richardson
# This file is part of Open Admin for Schools.
# Open Admin for Schools 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; version 2 of
# the License, only.
# Turn off subject smarts on line 484. These are for subject based
# entry and will use the timetable values if present.
my %lex = ('Global term start/end not defined in master configuration file' =>
'Global term start/end not defined in master configuration file',
'No Term Found' => 'No Term Found',
'Current Date' => 'Current Date',
'Verify that term dates are correctly set in the global configuration file' =>
'Verify that term dates are correctly set in the global configuration file',
'Periods per Day not set in configuration file' =>
'Periods per Day not set in configuration file',
'Student Attendance' => 'Student Attendance',
'Main' => 'Main',
'Enter Checks and Reasons for Students Missing ONLY' =>
'Enter Checks and Reasons for Students Missing ONLY',
'Date' => 'Date',
'Next Week' => 'Next Week',
'Previous Week' => 'Previous Week',
'Teacher Att Entries' => 'Teacher Att Entries',
'UserId' => 'UserId',
'Continue' => 'Continue',
'Cookie Duration' => 'Cookie Duration',
'Password' => 'Password',
'Please Log In' => 'Please Log In',
'Classes' => 'Classes',
'Clear Prev Attendance' => 'Clear Prev Attendance',
'Submit Attendance' => 'Submit Attendance',
'Student Not Found' => 'Student Not Found',
'Student Alias' => 'Student Alias',
'Entry' => 'Entry',
'Period' => 'Period',
'Enter 4 digits (3 digit alias + 1 digit period)' =>
'Enter 4 digits (3 digit alias + 1 digit period)',
'using numeric keypad and tab key only' => 'using numeric keypad and tab key only',
'Subject' => 'Subject',
'Enter 6 digits (3 digit alias + 2 digit subject + period)' =>
'Enter 6 digits (3 digit alias + 2 digit subject + period)',
'Student' => 'Student',
'AM' => 'AM',
'PM' => 'PM',
'Reason' => 'Reason',
'Sel' => 'Sel',
'Previous Attendance Entries' => 'Previous Attendance Entries',
'Edit Attendance' => 'Edit Attendance',
'Date/Per' => 'Date/Per',
'Name' => 'Name',
'Student Attendance' => 'Student Attendance',
'Term' => 'Term',
'Teacher' => 'Teacher',
'Room' => 'Room',
'Day In Cycle' => 'Day In Cycle',
'Period(s)' => 'Period(s)',
'No Scheduled Periods exist today' => 'No Scheduled Periods exist today',
'Mode' => 'Mode',
'All Subjects Shown' => 'All Subjects Shown',
'Fallback' => 'Fallback',
'Only Scheduled Subjects Shown' => 'Only Scheduled Subjects Shown',
'Method' => 'Method',
'Name' => 'Name',
'Error' => 'Error',
);
my $self = 'tattentry0.pl';
my $weekcount = 1; # Number of weeks to do for entry. (normally 1 or 2)
use DBI;
use CGI;
use CGI::Session;
use Time::JulianDay;
use Date::Business;
# These 4 variables are now moved into admin.conf (2.40+)
# my $maxterms = 12; # maximum # of terms to search for.
if ( not $g_maxterms ) { $g_maxterms = 12 };
# my $attendview = 16; # Number of previous attendance records to see;
if (not defined $g_attendview ) { $g_attendview = 16; }
# my $teachview = 12; # Number of teacher attendance records to see.
if (not defined $g_teachview ) { $g_teachview = 12; }
# my $allowedit = 1; # Comment out to disable teacher editing of att records.
if ( not defined $g_allowedit ) { $g_allowedit = 1; }
my $q = new CGI;
my %arr = $q->Vars;
my $method; # attendance entry 'method'
($dud,$method) = split /\(/, $arr{method};
chop $method; # remove trailing parens
eval require "../etc/admin.conf";
if ( $@ ) {
print $lex{Error}. " $@ \n";
die $lex{Error}. " $@ \n";
}
my $dsn = "DBI:$dbtype:dbname=$dbase";
my $dbh = DBI->connect($dsn,$user,$password);
# Get Session
my $session = new CGI::Session("driver:mysql;serializer:FreezeThaw",
undef,{Handle => $dbh}) or die CGI::Session->errstr;
# Get/Set Session Values (a defined userid means it was passed)
if ( $arr{userid} ){ # we want to login, passed userid/password pair.
# Check password/userid against database (-1 no user, -2 wrong password);
my $error = checkPassword($arr{userid}, $arr{password});
if ($error == -1){ print $q->header; login($lex{nouserid}); }
if ($error == -2){ print $q->header; login($lex{nopassword}); }
$cookietime = checkCookieTime( $arr{duration} );
# Set values for userid and logged_in in session
$session->param( 'logged_in','1');
$session->expire( 'logged_in', $cookietime );
$session->param( 'userid',$arr{userid} );
$session->param( 'duration',$cookietime );
$userid = $arr{userid};
} else { # check logged_in value in session
if ( not $session->param('logged_in') ){
$userid = $session->param('userid');
print $q->header;
login( $lex{'Please Log In'}, $userid );
die;
}
# Ok, we have a login. Values below we have in environment.
$userid = $session->param('userid');
$duration = $session->param('duration');
if ( not ($duration =~ /\+/)) { # if not in +20m format, do so.
$duration = checkCookieTime( $duration );
}
$session->expire('logged_in', $duration );
} # End of check for logged_in value
print $session->header;
# Print HTML Page Header....
print "$doctype\n
". $lex{'Student Attendance'}. "
$chartype\n\n";
# foreach my $key (keys %arr ) { print "K: $key V: $arr{$key} \n"; }
print "[ ". $lex{Main}. " ]\n";
print "". $lex{Method}. " $method\n";
# Date Functions - current date, date data structures.
if ( not $schoolstart ){ $schoolstart = $g_termstart{1};}
my ($styear,$stmonth,$stday) = split /-/,$schoolstart;
my ($endyear,$endmonth,$endday) = split /-/,$schoolend;
my $startjd = julian_day($styear,$stmonth,$stday);
my $endjd = julian_day($endyear,$endmonth,$endday);
my ($currdate,$currsdate);
if ( $arr{date} ) {
# Generate a list from those dates. Assume year-mon-day
($year,$month,$day) = split /-/,$arr{date};
$jd = julian_day($year,$month,$day);
$dow = day_of_week($jd);
$mondayjd = $jd - ($dow-1);
# Check for date before start of year; reset to year start.
#if ($mondayjd < $startjd ){ $mondayjd = $startjd;}
if (length($month) == 1){ $month = "0".$month;}
if (length($day) == 1){ $day = "0".$day;}
$currsdate = "$year$month$day";
$currdate = "$year-$month-$day";
} else {
@tim = localtime(time);
$year = $tim[5] + 1900;
$month = $tim[4] + 1;
$day = $tim[3];
$jd = julian_day($year,$month,$day);
$mondayjd = $jd - ($tim[6]-1); #This will now give Monday of that week.
if (length($month) == 1){ $month = "0".$month;}
if (length($day) == 1){ $day = "0".$day;}
$currdate = "$year-$month-$day";
$currsdate = "$year$month$day";
}
if (not %g_termstart){
print $lex{'Global term start/end not defined in master configuration file'};
print " (admin.conf)!\n";
print "\n";
die $lex{'Global term start/end not defined in master configuration file'};
}
# Figure out the current term
my ( $term,$termoffset );
my $dateobj = new Date::Business(DATE=>$currsdate);
#foreach my $t ( keys %g_termstart ) { print "K:$t V:$g_termstart{$t} \n"; }
for my $trm ( sort keys %g_termstart ) {
if ( $trm =~ m/\D/ ) { next;} # skip if not a digit... (when multiTrack)
# Get term offset from today.
my $startdate = $g_termstart{$trm};
$startdate =~ s/-//g;
my $startobj = new Date::Business(DATE => $startdate);
$termoffset = $dateobj->diffb($startobj,'prev','next');
#print " Trm: $trm Date: $startdate Offset: $termoffset \n";
if ( $termoffset < 0 ){
# Offset will be 0 or > 0 when we just pass into next term.
# Negative values will be days ahead... the "first" negative
# will be the next term (and thus we haven't got there
# yet. Subtract 1 from current term and we are in the term of
# interest. It will be term 0 before the first term...
$term = $trm - 1; last;
} else {
$term = $trm;
}
}
if ( not $term ) { # No term found!
print "
". $lex{'No Term Found'}. ".
\n
";
print $lex{'Verify that term dates are correctly set in the global configuration file'}. ".\n";
print $lex{'Current Date'}. ": $currdate
\n";
print "\n";
die;
}
# Set Maximum periods per day; (Used by Subject entry and MultiDay)
my $maxppd = 0; # Maximum periods per day
if (not %g_ppd){
print $q->header;
print $lex{'Periods per Day not set in configuration file'}. "! \n";
die;
}
foreach my $key (keys %g_ppd){ # Get the Largest PPD.
if ($g_ppd{$key} > $maxppd){ $maxppd = $g_ppd{$key};}
}
# Setup Array and Hash to hold Dates and DOW Dates (Multi-Day Method)
mkDateData($mondayjd,$weekcount);
# Push Rooms into array
my $sth = $dbh->prepare("select distinct homeroom from staff
where userid = ? and homeroom != '' and homeroom is not null");
$sth->execute($userid);
if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
while ( my $homeroom = $sth->fetchrow ) {
push @hroom, $homeroom;
}
# Rest of Top of Page...
#print $currdate;
print "
\n\n";
my $sth3 = $dbh->prepare("select * from tattend
where techid = ? order by date desc");
$sth3->execute($userid);
if ($DBI::errstr){ print $DBI::errstr; die;}
$trows = $sth3->rows;
# Limit View to the $g_teachview value (set in admin.conf)
if ( $trows > $g_teachview ){ $trows = $g_teachview; }
print "
". $lex{'Teacher Att Entries'}. "
\n";
print "
\n";
print "
". $lex{UserId}. "
". $lex{Date}. "
\n";
for (1..$trows){
@tattend = $sth3->fetchrow;
print "
$tattend[1]
$tattend[2]
\n";
}
print "
\n";
if ($method ne 'subject'){ # Not High School Entries
print "
". $lex{'Previous Attendance Entries'}. "
\n";
foreach $hroom (@hroom) {
if ( $g_allowedit ){
print "\n";
}
$sth3 = $dbh->prepare("select * from attend, student
where attend.studentid = student.studnum and student.homeroom = ?
order by attend.absdate desc, student.lastname,
student.firstname, attend.period");
$sth3->execute($hroom);
if ($DBI::errstr) { print $DBI::errstr; die;}
$rows = $sth3->rows;
# Only print the value of $g_attendview attendance records
if ($rows > $g_attendview) {
$rows = $g_attendview;
}
print "
". $lex{Name}. "
". $lex{'Date/Per'}. "
\n";
for ($i=1; $i <= $rows; ++$i) {
@arr = $sth3->fetchrow;
if ( $g_allowedit ) {
print "
print"\n";
$nextjd = $mondayjd + 7;
if ($nextjd > $endjd){ $nextjd = $endjd;}
($nextyear, $nextmonth, $nextday) = inverse_julian_day($nextjd);
$nextdate = "$nextyear-$nextmonth-$nextday";
print "\n \n";
$sth = $dbh->prepare("select dayincycle from dates where date = ?");
# Main Attendance Entry begins here.
if ($method ne 'multiday'){
# multiday calls a different script to allow for reason entry
# before going to confirmation in tattentry1 script.
if ( $method ne 'subject' ) {
print "\n";
$mondayjd++;
}
print "
\n";
#-------------
sub mkDateData {
#-------------
my ($jd, $weeks) = (@_);
# Build an array of ISO dates and a hash using them
# as keys to hash values of 'Mon Jan 6' format.
# If one week, then just 5 values, if two wk then 10, etc.
for (1..$weeks){
for (1..5){
my ($yr,$mon,$day) = inverse_julian_day($jd);
my $dow = day_of_week($jd) + 1;
push @days, "$yr-$mon-$day";
$datedata{"$yr-$mon-$day"} = "$dow[$dow], $month[$mon] $day";
$jd++;
}
$jd = $jd + 2; # skip over weekend.
}
}
#----------------
sub checkPassword {
#----------------
my ($userid, $password) = @_;
if (not $userid){ return -1;}
if (not $password){ return -2;}
#check for presence of userid
my $sth = $dbh->prepare("select count(userid) from staff
where userid = ?");
$sth->execute($userid);
if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
my $count = $sth->fetchrow;
if ($count < 1){ return -1;} # no userid
#check for presence of correct password and userid
my $sth = $dbh->prepare("select count(userid) from staff
where userid = ? and passwd = ? ");
$sth->execute($userid, $password);
if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
my $count = $sth->fetchrow;
if ($count < 1){ return -2;} # not correct password
return 0; # if all ok...
}
#------------------
sub checkCookieTime {
#------------------
# Requires defaults of: $defaulttime, $maximumtime, $minimumtime
$defaulttime = 5;
$maximumtime = 60;
$minimumtime = 3;
my $duration = shift;
if ($duration) {
$cookietime = $duration;
} else {
$cookietime = $defaulttime;
}
$cookietime = $minimumtime if $cookietime < $minimumtime;
$cookietime = $maximumtime if $cookietime > $maximumtime;
$cookietime = "+". $cookietime."m"; # set format
return $cookietime;
}
#--------
sub login { # print error, login screen and die;
#--------
# Requires $lex values for: Continue, UserId, Password, Cookie Duration, Please Log In
my $error = shift;
my $userid = shift; # may not be present...
if (not $error) { $error = $lex{'Please Log In'}; }
print "$doctype\n$error
$chartype\n\n";
print "\n";
print "[ ". $lex{Main}. " ]\n";
print "