#!/usr/bin/perl # Copyright 2001-2007 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 466. 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)', ); 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; my $maxterms = 12; # maximum # of terms to search for. my $attendview = 16; # Number of previous attendance records to see; my $teachview = 12; # Number of teacher attendance records to see. my $allowedit = 1; # Comment out to disable teacher editing of att records. my @month = ('','Jan','Feb','Mar','Apr','May','Jun', 'Jul','Aug','Sep','Oct','Nov','Dec'); my @week = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); my $q = new CGI; my %arr = $q->Vars; my $method; # attendance entry 'method' ($dud,$method) = split /\(/, $arr{method}; chop $method; # remove trailing parens require "../etc/admin.conf" || die "Cannot open admin.conf!"; 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}); die;} if ($error == -2){ print $q->header; &login($lex{nopassword}); die; } $cookietime = checkCookieTime( $arr{duration} ); # Set values for userid and logged_in in session $session->param('logged_in','1'); $session->expire('logged_in','+20m'); $session->param('userid',$arr{userid}); $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'); $cookietime = checkCookieTime( $duration ); $session->expire('logged_in', $cookietime ); } # End of check for logged_in value print $session->header; # Print HTML Page Header.... print "$doctype\n". $lex{'Student Attendance'}. " $chartype\n\n"; print "[ ". $lex{Main}. " ]\n"; #print "Dur:$duration: Cookietime: $cookietime
\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"; } my $dateobj = new Date::Business(DATE=>$currsdate); if (not %g_termstart){ print $q->header; print $lex{'Global term start/end not defined in master configuration file'}; print " (admin.conf)!\n"; die; } # Figure out the current term, if not passed term my $term = 0; for (1..$maxterms){ # 12 is worst case scenario.. what's reasonable? my $startdate = $g_termstart{$_}; $startdate =~ s/-//g; my $startobj = new Date::Business(DATE => $startdate); my $enddate = $g_termend{$_}; $enddate =~ s/-//g; #print "SD: $startdate ED: $enddate
\n"; my $endobj = new Date::Business(DATE => $enddate); $startoffset = $dateobj->diffb($startobj,'prev','next'); $endoffset = $dateobj->diffb($endobj,'prev','next'); #print "StartOffset: $startoffset Endoffset: $endoffset
\n"; if ($startoffset >= 0 and $endoffset <= 0){ # Above now works correctly... # Note: values advance like this: At EOT: StartOffset 20 EndOffset 0 for currterm. # and next term will have values of -1 and -29. The next day, # At SOT (Start of Term) 21 1 and 0 -28 $term = $_; last; } } if (not $term){ # No term found! print $q->header; 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'}. ": $currsdate

\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 $sth = $dbh->prepare("select distinct homeroom from staff where userid = ? and homeroom != ''"); $sth->execute($userid); if ($DBI::errstr){ print $DBI::errstr; die; } while (my $homeroom = $sth->fetchrow){ push @hroom, $homeroom; } # Rest of Top of Page... print $currdate; print "

\n". $lex{'Student Attendance'}. q{ }; print $lex{Entry}. " – ". $lex{Term}. " $term

\n"; print "\n"; 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; if ($trows > $teachview){ $trows = $teachview;} print "

". $lex{'Teacher Att Entries'}. "

\n"; print "\n"; print "\n"; for (1..$trows){ @tattend = $sth3->fetchrow; print "\n"; } print "
". $lex{UserId}. "". $lex{Date}. "
$tattend[1]$tattend[2]
\n"; if ($method ne 'subject'){ # Not High School Entries print "

". $lex{'Previous Attendance Entries'}. "

\n"; foreach $hroom (@hroom) { if ($allowedit){ print "
\n"; 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; if ($rows > $attendview) { $rows = $attendview; } # Only print the value of $attendview attendance records print "\n"; for ($i=1; $i <= $rows; ++$i) { @arr = $sth3->fetchrow; if ($allowedit){ print "\n"; } else { # not allowed to edit print "\n"; } print "\n"; } print "
". $lex{Name}. "". $lex{'Date/Per'}. "
\n"; print "$arr[8], $arr[9]
$arr[8], $arr[9]$arr[2]/$arr[4]
\n"; } } # End of Not Subject Method print "
\n"; print "\n"; print "
\n"; print $lex{'Enter Checks and Reasons for Students Missing ONLY'}. "
\n"; print "

\n\n"; # ============== $prevjd = $mondayjd - 7; if ($prevjd < $startjd){ $prevjd = $startjd;} ($prevyear, $prevmonth, $prevday) = inverse_julian_day($prevjd); $prevdate = "$prevyear-$prevmonth-$prevday"; print "\n\n"; $nextjd = $mondayjd + 7; if ($nextjd > $endjd){ $nextjd = $endjd;} ($nextyear, $nextmonth, $nextday) = inverse_julian_day($nextjd); $nextdate = "$nextyear-$nextmonth-$nextday"; print "
\">
\n\n"; # 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"; print "\n"; print "\n"; print "". $lex{Date}. ":

\n\n\n"; } else { # subject method for (my $i=1; $i<=5; $i++) { ($wkyear, $wkmonth, $wkday) = inverse_julian_day($mondayjd); $dow = day_of_week($mondayjd); my $tmpdate = "$wkyear-$wkmonth-$wkday"; print "\n"; print "\n"; print "\n"; print "\n"; print "
\n"; $mondayjd++; } print "
\n"; print "\n"; print "\n"; print "

". $lex{Date}. ": $currdate

\n"; print "\n"; } } # Entry Methods Start Here. # ============= if ($method eq 'subject'){ require "../lib/libschedule.pl" or die "Cannot open libschedule.pl!\n"; # need $additionalcomments subject name to skip... require "../etc/repcard.conf" or die "Cannot open repcard.conf!\n"; # Get subjects taught this term by this teacher; create %subjects my %subjects; my $sth= $dbh->prepare("select subjsec, smdesc, description from subject where subject.teacher $sql{like} '%($userid%' and $term >= subject.startrptperiod and $term <= subject.endrptperiod"); $sth->execute; if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; } my $sth1 = $dbh->prepare("select count(*) from eval where subjcode = ?"); while ( my ( $subjsec, $smdesc, $description ) = $sth->fetchrow ) { if ( $description eq $additionalcomments ) { next; } # skip additional comment subjects $sth1->execute($subjsec); if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; } my $count = $sth1->fetchrow; if ($count < 1) { next; } # skip if no enrolled students. if (not $smdesc ) { # use description if not small description. $description =~ s/\s+//g; # strip spaces. $smdesc = substr($description,0, 7); } $subjects{$subjsec} = $smdesc; } #foreach my $subjsec ( keys %subjects ) { print "$subjsec - $subjects{$subjsec}
\n"; } # Get the current DayInCycle; my $dayInCycle = findDayInCycle( $currdate, $dbh ); if ($dayInCycle) { print $lex{'Day In Cycle'}. ": $dayInCycle
\n"; } # Get periods taught today. my $sth= $dbh->prepare("select schedat.subjsec, schedat.period from subject, schedat where subject.teacher $sql{like} '%($userid%' and $term >= subject.startrptperiod and $term <= subject.endrptperiod and schedat.subjsec = subject.subjsec and schedat.day = '$dayInCycle' order by period"); $sth->execute; if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; } my %periods; # holds period and matching subjsec. while ( my ($subjsec, $period) = $sth->fetchrow) { #print "S:$subjsec P:$period
\n"; if ( exists $subjects{$subjsec} ) { # we have a subject with kids... $periods{"$period:$subjsec"} = $subjects{$subjsec}; # which is description... } } my $periodsDefined; # turn off new function... #--------------- #%periods = (); #--------------- if (not %periods) { # no timetable values found, fall back to load them all my $counter = 1; foreach my $subjsec (keys %subjects) { my $key = "$counter:$subjsec"; #print "Subject: $subjsec P:$counter
\n"; $periods{$key} = $subjects{$subjsec}; $counter++; } } else { # build classes from periods hash $periodsDefined = 1; } #foreach my $key (sort keys %periods) { print "P:$key Sub: $periods{$key}
\n"; } # print hyperlink row my $first = 1; print "[ "; foreach my $key (sort keys %periods) { my ($period, $subjsec) = split /:/, $key; if (not $first ) { print " |\n"; } else { $first = 0; } print "$period-$periods{$key} "; } print "]\n"; my $sth2 = $dbh->prepare("select description from subject where subjsec = ?"); foreach my $key (sort keys %periods) { my ($period, $subjsec) = split /:/, $key; # Get the description for the subject $sth2->execute($subjsec); if ($DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } my $description = $sth2->fetchrow; # Get the Kids first... studnums. $sth = $dbh->prepare("select distinct eval.studnum from eval,student where subjcode = ? and eval.studnum = student.studnum order by student.lastname,student.firstname"); $sth->execute($subjsec); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } my $rows = $sth->rows; if ($rows < 1){ next;} # No students registered. print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; my $sth1 = $dbh->prepare("select lastname,firstname from student where studnum = ?"); # Loop Through Students for (1..$rows) { my $studnum = $sth->fetchrow; $sth1->execute($studnum); if ($DBI::errstr) { print $DBI::errstr; die; } my ($lastname,$firstname) = $sth1->fetchrow; if ( not $lastname ){ # student name not found. $lastname = "". $lex{'Student Not Found'}. ""; } print "\n"; } print "\n"; print "
$description ($subjsec)
". $lex{Student}. "". $lex{'Period(s)'}; print " – ". $lex{Reason}. "
\n"; print "\n"; print "
\n"; print "$lastname, $firstname\n"; if ( $periodsDefined ) { print"P$period\n"; } else { for (1..$maxppd){ print"P$_\n"; } } if ( $periodsDefined ) { print "
\n"; print "\n"; print "

\n"; } # Outer Loop here for each subject. } # End of SUBJECT Method elsif ($method eq 'sa4') { # Student Alias, 4 digits print "

". $lex{'Student Alias'}. " + ". $lex{Period}. q{ }. $lex{Entry}. "

\n"; print $lex{'Enter 4 digits (3 digit alias + 1 digit period)'}. "
\n"; print $lex{'using numeric keypad and tab key only'}. ".
\n"; print "\n"; for ($i=1;$i<=20;$i++) { # Setup 20 Input Entries print "\n"; if (not ($i % 5)){ print "\n";} } print "
\n"; } # End of SA4 Method elsif ($method eq 'sa6') { # Student Alias, Subject, Period - 6 digits print "

". $lex{'Student Alias'}. " + ". $lex{Subject}. " + ". $lex{Period}. q{ }. $lex{Entry}. "

\n"; print $lex{'Enter 6 digits (3 digit alias + 2 digit subject + period)'}. "
\n"; print $lex{'using numeric keypad and tab key only'}. ".
\n"; print "\n"; for ($i=1;$i<=20;$i++) { # Setup 20 Input Entries print "\n"; if (not ($i % 5)){ print "\n";} } print "
\n"; } # End of SA6 Method # MULTIDAY Method elsif ($method eq 'multiday') { # Multi-Day Method print " \n"; # Find the kids' names and studnum my $sth = $dbh->prepare("select lastname, firstname, studnum from student where homeroom = ? order by lastname, firstname"); foreach my $hroom (@hroom) { $sth->execute($hroom); if ($DBI::errstr){ print $DBI::errstr; die "$DBI::errstr\n";} print "\n"; # Print table headings. print ""; foreach my $day (@days){ print "";} print "\n"; # Loop through kids displaying the values. while (my ($lastname, $firstname, $studnum) = $sth->fetchrow){ # print Name. print "\n"; # print the days for this mode: foreach my $day (@days){ print ""; } print "\n"; } print "
Name$datedata{$day}
$lastname, $firstname"; for (1..$maxppd){ print "P$_\n"; if ($_ % 2 == 0){ print "
";} } print "
\n"; } # End of This Homeroom (in case of multiple) } # End of Multi-Day Method else { # If not Subject, SA4 or SA6 methods, then use SNAP. # Get Teacher Name my $sth = $dbh->prepare("select sal, lastname, firstname from staff where userid = ?"); $sth->execute($userid); if ($DBI::errstr) { print $DBI::errstr; die; } my ($tsal, $tlastname, $tfirstname) = $sth->fetchrow; my $teacher; if ($tsal) { $teacher = "$tsal $tfirstname $tlastname"; } else { $teacher = "$tfirstname $tlastname"; } $sth = $dbh->prepare("select lastname, firstname, studnum from student where homeroom = ? order by lastname, firstname"); foreach my $hroom (@hroom) { $hroom =~ s/\s+//g; $sth->execute($hroom); if ($DBI::errstr) { print $DBI::errstr; die; } $rows = $sth->rows; print "
". $lex{Teacher}. "\n"; print " $teacher  ". $lex{Room}. " \n"; print "$hroom
\n\n"; print "\n"; print "\n"; print "\n"; while (my ($lastname, $firstname, $studnum) = $sth->fetchrow){ print "\n"; print "\n"; if ( $maxppd != 1 ) { print "\n"; } print "\n"; } print "\n"; print "
\n"; print "\n"; print "
". $lex{Student}. ""; if ( $maxppd == 1 ) { print $lex{Sel}; } else { print $lex{AM}. "". $lex{PM}; } print "". $lex{Reason}. "
$lastname, $firstname
\n"; print "\n"; print "

\n"; } # Outer Loop here for each grade. } # End of ELSE Entry Method 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); push @days, "$yr-$mon-$day"; $datedata{"$yr-$mon-$day"} = "$week[$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; if (not $error) { $error = $lex{'Please Log In'}; } print "$doctype\n$error $chartype\n\n"; print "\n"; print "[ ". $lex{Main}. " ]\n"; print "

$error

\n"; print "
\n"; print "\n"; print "\n"; print "\n"; print "\n"; #value=\"$userid\" print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "
". $lex{UserId}. "
". $lex{Password}. "
". $lex{'Cookie Duration'}. "
\n"; print "
\n"; print "
\n"; die; }