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

#  This file is part of Open Admin for Schools.


my %lex = ('Staff' => 'Staff',
	   'Preregistration' => 'Preregistration',
	   'Main' => 'Main',
	   'Eoy' => 'Eoy',
	   'Staff Member' => 'Staff Member',
	   'User Id' => 'User Id',
	   'Home' => 'Home',
	   'Room' => 'Room',
	   'Course' => 'Course',
	   'Edit' => 'Edit',
	   'Delete' => 'Delete',
	   'Error' => 'Error',
	   'Grade' => 'Grade',
	   'Access' => 'Access',
	   'Position' => 'Position',
	   'Count' => 'Count',
	   'Red' => 'Red',
	   'Absence' => 'Absence',
	   'Reason' => 'Reason',
	   'Day' => 'Day',
	   'Part' => 'Part',
	   'Save' => 'Save',
	   'Date' => 'Date',
	   'AM' => 'AM',
	   'PM' => 'PM',
	   'All Day' => 'All Day',
	   'Record Exists' => 'Record Exists',
	   'Skipping' => 'Skipping',
	   'Record Stored' => 'Record Stored',
	   'Absent' => 'Absent',
	   'Continue' => 'Continue',
	   'No Entry' => 'No Entry',
	   'Out of Range' => 'Out of Range',
	   'Invalid Date' => 'Invalid Date',
	   'Missing' => 'Missing',
	   'Other' => 'Other',
	   'Late' => 'Late',
	   
	   );


my $self = 'staffabsadd.pl';

my @dayparts; # put in translated values, if necessary.
foreach my $dp ( 'AM', 'PM', 'All Day' ) {
    push @dayparts, $lex{$dp};
}


use DBI;
use CGI;
use Time::JulianDay;

eval require "../../etc/admin.conf";
if ( $@ ) {
    print $lex{Error}. ": $@<br>\n";
    die $lex{Error}. ": $@\n";
}

# Load audit write function
eval require "../../lib/libaudit.pl";
if ( $@ ) {
    print $lex{Error}. ": $@<br>\n";
    die $lex{Error}. ": $@\n";
}


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


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



my @tim = localtime(time);
my $year = $tim[5] + 1900;
my $month = $tim[4] + 1;
my $day = $tim[3];
if (length($month) == 1){ $month = "0".$month;}
if (length($day) == 1){ $day = "0".$day;}
my $currdate = "$year-$month-$day";


# Print Page Header
my $title = "Add $lex{Staff} $lex{Absence}";

print qq{$doctype\n<html><head><title>$title</title>
<link rel="stylesheet" href="$css" type="text/css">
$chartype\n};

if ( not $arr{page} ) { # date function
    print qq{<link rel="stylesheet" type="text/css" media="all" };
    print qq{href="/js/calendar-blue.css" title="blue">\n};
    print qq{<script type="text/javascript" src="/js/calendar.js"></script>\n};
    print qq{<script type="text/javascript" src="/js/lang/calendar-en.js"></script>\n};
    print qq{<script type="text/javascript" src="/js/calendar-setup.js"></script>\n};
}


print qq{</head>\n<body style="padding:1.5em;">[ <a href="$homepage">$lex{Main}</a> ]\n};

print qq{<h1>$title</h1>\n};


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

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

} elsif ( $arr{page} == 2 ) {
    delete $arr{page};
    writeRecords();
}



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

    my $sth1 = $dbh->prepare("select field_value from staff_multi
     where field_name = ? and userid = ?");

    # select values from staff/prereg_staff table.
    $sth = $dbh->prepare("select id, lastname, firstname, userid
     from staff order by lastname, firstname");
    $sth->execute;
    if (DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    

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

    # Get the date
    print qq{<table style="padding:1em;font-weight:bold;font-size:120%;border:1px solid black;};
    print qq{float:left;margin:1em;">\n};
    print qq{<tr><td>$lex{Absent} $lex{Date}\n};
    print qq{<input type="text" name="date" id="date" size="10" value="$currdate">\n};
    print qq{<button type="reset" id="start_trigger">...</button></td></tr></table>\n};

    # Explanation
    print qq{<table style="padding:0.5em;font-size:120%;};
    print qq{border:1px solid black;float:left;width:60ch;margin:1em;">\n};
    print qq{<tr><td>For <b>Late</b> Entries simply put the number in the late column</td></tr>\n};
    print qq{<tr><td>For <b>Normal</b> entries select values from the <b>Day Part</b>\n};
    print qq{and the <b>Reason</b>.\n};
    print qq{If no appropriate reason, put a value in the <b>Other</b> column</td></tr></table>\n};

    print qq{<div style="clear:left;"></div>\n};
    
    # Table
    print qq{<table cellpadding="3" border="1" cellspacing="0">\n};
    print qq{<tr><th>$lex{'Staff Member'}</th><th>$lex{'User Id'}</th><th>$lex{Position}</th>\n};
    print qq{<th>$lex{Day}<br>$lex{Part}</th><th>$lex{Reason}</th>};
    print qq{<th>$lex{Reason}<br>$lex{Other}</th><th>$lex{Late}<br>(minutes)</th></tr>\n};

    print qq{<tr><td colspan="7" class="la"><input type="submit" value="$lex{Continue}"></td></tr>\n};
    
UID:    while ( my ( $id, $lastname, $firstname, $userid ) = $sth->fetchrow) {

	# Load Positions (Jobs)
	$sth1->execute( 'position', $userid );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my $positions;
	my $first = 1;
	while ( $pos = $sth1->fetchrow ) {
	    if ( not $g_StaffAbsPos{$pos} ) { next UID;}
	    if ( not $first ) { $positions .= ', '; } else { $first = 0; }
	    $positions .= $pos;
	}


	print qq{<tr><td><b>$lastname</b>, $firstname</td><td>$userid</td><td>$positions</td>\n};

	# Day Parts
	print qq{<td><select name="F:$userid"><option></option>\n};
	foreach my $part ( @dayparts ) { # defined at top; also translated.
	    print qq{<option>$part</option>};
	}
	print qq{</select></td>\n};


	# Absence Reasons
	print qq{<td><select name="R:$userid"><option></option>\n};
	foreach my $rsn ( @g_StaffAbsReason ) {
	    print qq{<option>$rsn</option>};
	}
	print qq{</select></td>\n};

	# Other Reason
	print qq{<td><input type="text" name="O:$userid" size="12"></td>};
    
	# Late Minutes
	print qq{<td><input type="text" name="L:$userid" size="5"></td>};

	print qq{</tr>\n};

    }

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

    print qq{<script type="text/javascript">
     Calendar.setup({
      inputField     :    "date", // id of the input field
      ifFormat       :    "%Y-%m-%d", // format of the input field
      button         :    "start_trigger", // trigger for the calendar (button ID)
      singleClick    :    false,        // double-click mode
      step           :    1             // show all years in drop-down boxes
      });
     </script>\n};

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

    exit;
} # end of showStartPage


#---------------
sub confirmEntry {
#---------------

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

    print qq{<h3>Absence Confirmation Page</h3>\n};

    my $date = $arr{date};
    delete $arr{date};

    # Check Date for not in future (more than 7 days) and within current school year, and validity.
    if ( not checkdate( $date ) ) { 
	print qq{<h3>$lex{'Invalid Date'}</h3>\n};
	print qq{</body></html>\n};
	exit;
    }

    my $currjd = julian_day( split('-', $currdate));	
    my $startjd = julian_day( split('-', $schoolstart)); # global var
    my $datejd = julian_day( split('-', $date));
    if ( $datejd > $currjd + 7 or $datejd < $startjd ) {
	print qq{<h3>$lex{Error}: $lex{Date} $lex{'Out of Range'}</h3>\n};
	print qq{</body></html>\n};
	exit;
    }
    # Done date checking.

    my %data;
    # assemble data into records.
    foreach my $key ( sort keys %arr ) {
	if ( not $arr{$key} ) { next; } # skip if no value
	my ( $type, $userid ) = split(':', $key);
	$data{$userid}{$type} = $arr{$key};
    }

    # Testing
#    print qq{<div>Date:$date</div>\n};
#    foreach my $userid ( sort keys %data ) {
#	foreach my $type ( sort keys %{ $data{$userid}} ) {
#	    print qq{Userid:$userid  Type:$type Value:$data{$userid}{$type}</div>\n};
#	}
#    }

    
    my %nextdata; # data passed to the next page;

    # Check for existing record
    my $sth1 = $dbh->prepare("select count(*) from staff_absent where 
			     adate = ? and userid = ?");
    # Get Staff Name
    my $sth2 = $dbh->prepare("select lastname, firstname from staff where userid = ?");

    
    foreach my $userid ( sort keys %data ) {

	# Get Name, in case we need it.
	$sth2->execute($userid );
	if (DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my ($lastname, $firstname) = $sth2->fetchrow;

	
	# Checking for existing records.  (Daypart removed since too
	# complex. They can edit if they want)
	$sth1->execute($date, $userid );
	if (DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my $count = $sth1->fetchrow;
	if ( $count ) { # skip
	    print qq{<div>Record exists. Skipping $firstname $lastname ($userid) $date</div>\n};
	    next; # userid
	}
	
	if ( not $data{$userid}{'L'} ) { # no late value then check for other fields filled.
	    # Late value means we don't care about other values; may be present or not.
	    if ( not $data{$userid}{'F'} ) { # daypart
		print qq{<h3>$lex{Error}: $lex{Missing} $lex{Day} $lex{Part} / };
		print qq{$firstname $lastname</h3>\n};
		next; # userid
	    }

	    # Can't use this since they can remove the 'Other' reason.
	    # if ( $data{$userid}{'R'} eq 'Other (specify)' and not $data{$userid}{'O'} ) { 
	    # print qq{<h3>$lex{Error}: $lex{Missing} $lex{Reason} / $firstname $lastname</h3>\n};
	    # next;
	    # }
	}

	# IF we're here, we add to the next data hash.
	foreach my $userid ( sort keys %data ) {
	    foreach my $type ( keys %{ $data{$userid}} ) {
		$nextdata{$userid}{$type} = $data{$userid}{$type};
	    }
	}
	
    } # end of userid loop

    # Testing
#    print qq{<div>Date:$date</div>\n};
#    foreach my $userid ( sort keys %nextdata ) {
#	foreach my $type ( sort keys %{ $nextdata{$userid}} ) {
#	    print qq{Userid:$userid  Type:$type Value:$nextdata{$userid}{$type}</div>\n};
#	}
#    }

   

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

    # We can now pass %nextdata to next page.
    my %typemap = ( 'R' => 'Reason', 'L' => 'Late', 'O' => 'Other Reason', 'F' => 'Day Part');
    
    # Write the hidden values for next page
    print qq{<p><b>Date</b>: $date</p>\n};
    print qq{<input type="hidden" name="date" value="$date">\n};
    foreach my $userid ( sort keys %nextdata ) {
	foreach my $type ( sort keys %{$nextdata{$userid}} ) {
	    my $name = qq{$userid:$type};
	    my $value = $nextdata{$userid}{$type}; 
	    print qq{<input type="hidden" name="$name" value="$value">\n};
	    print qq{<p><b>Userid</b>:$userid <b>Type</b>:$typemap{$type} <b>Value</b>:$value</p>\n};
	}
    }

    print qq{<input type="submit" value="$lex{Save}">\n};
    print qq{</form>\n};

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

    exit;

}


#---------------
sub writeRecords {
#---------------

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

    my $date = $arr{date};
    delete $arr{date};

    if ( not $date ) {
	print qq{<div>Error: Missing Date</div>\n};
	print qq{</body></html>\n};
	exit;
    }

    
    # again, wrap into data structure
    my %data;
    # assemble data into records.
    foreach my $key ( sort keys %arr ) {
	if ( not $arr{$key} ) { next; } # skip if no value
	my ( $userid, $type ) = split(':', $key); # note reversed from start page
	$data{$userid}{$type} = $arr{$key};
    }

    # Testing
#    print qq{<div>Date:$date</div>\n};
#    foreach my $userid ( sort keys %data ) {
#	foreach my $type ( sort keys %{ $data{$userid}} ) {
#	    print qq{<div>Userid:$userid  Type:$type Value:$data{$userid}{$type}</div>\n};
#	}
#    }

    # These now map type to a field name
    my %typemap = ( 'R' => 'reason', 'L' => 'late', 'O' => 'other', 'F' => 'daypart');

    
    my $sth1 = $dbh->prepare("select lastname, firstname from staff where userid = ?");
    my $sth2 = $dbh->prepare("select * from staff_absent where userid = ? and adate = ?");
    
    foreach my $userid ( sort keys %data ) {

	# Get Name
	$sth1->execute( $userid );
	if (DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my ( $lastname, $firstname ) = $sth1->fetchrow;
	
	# Date
	my (@fields, @values, @qst);
	push @fields, 'adate'; # populate adate field.
	push @qst, '?';
	push @values, $date;
	# Userid
	push @fields, 'userid'; # populate adate field.
	push @qst, '?';
	push @values, $userid;
	# Name fields;
	push @fields, 'lastname';
	push @qst, '?';
	push @values, $lastname;

	push @fields, 'firstname';
	push @qst, '?';
	push @values, $firstname;
	
	foreach my $type ( sort keys %{ $data{$userid}} ) {
	    my $field = $typemap{$type};
	    push @fields, $field;
	    push @qst, '?';
	    push @values, $data{$userid}{$type};
	}

	my $fields = join(',',@fields);
	my $qst = join(',',@qst);
	# values stay as array @values

#	print qq{Fields:$fields QST:$qst VAL:@values<br>\n};

	
	my $sth = $dbh->prepare("insert into staff_absent ( $fields ) values( $qst )");
	$sth->execute( @values );
	if (DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	
	print qq{<div>$lex{'Record Stored'}: <b>$firstname $lastname</b> / $date / };
	print qq{ $data{$userid}{'F'}</div>\n};

    } # end of userid loop


    # Load Current Record for audit
    $sth2->execute( $userid,$date );
    if (DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    my $startref = $sth2->fetchrow_hashref;
    my $recid = $startref->{id};
    my %r = %$startref;
	
    # print "StartREF:$startref\n";
    #foreach my $key ( sort keys %r ) {
    #    print "K:$key VAL:$r{$key}<br>\n";
    #}
	
	
    my %audit;
    $audit{userid} = $ENV{REMOTE_USER};
    $audit{ipaddr} = $ENV{REMOTE_ADDR};
    $audit{scriptname} = $self;
    $audit{tablename} = 'staff_absent';
    $audit{tableid} = $startref->{id};
    #$audit{startval} = $startref; # nothing to start, data to end
    $audit{endval} = $startref;
    
    addAudit( \%audit, $dbh );

    # print qq{<h3>$lex{Audit} $lex{'Record Stored'}</h3>\n};

    print qq{<p>[ <a href="$homepage">$lex{Main}</a> | \n};
    print qq{ <a href="$self">$title</a> ]</p>\n};

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

    exit;

} # End of writeRecords



#------------
sub checkdate {  # check date for validity
#------------

    my @mdays = (0,31,28,31,30,31,30,31,31,30,31,30,31);
    my $maxyear = 2100;

    my $val = shift;

    if ( not $val =~ m/-/ ) {  # fail if no hyphens
	return undef;
    }

    # Strip Spaces
    $val =~ s/^\s+//g;
    $val =~ s/\s+$//g;

    my ( $year, $month, $day) = split(/-/, $val);


    # Check for non-digits
    if ($year =~ m/\D/) { return undef; }
    if ($month =~ m/\D/) { return undef; }
    if ($day =~ m/\D/) { return undef; }

    # reset Feb max days, if leap years
    if ($month == 2) {
	if ($year % 4 != 0) { $mdays[2] = 28; }
	elsif ($year % 400 == 0) { $mdays[2] = 29; }
	elsif ($year % 100 == 0) { $mdays[2] = 28; }
	else { $mdays[2] = 29; }
    }

    # check ranges
    if ( $day < 0 or $day > $mdays[$month] ) { # days out of range
	return undef;
    } elsif ( $month < 0 or $month > 12 ) { # month error
	return undef;
    } elsif ( $year < 0 or $year > $maxyear ) {
	return undef;
    }

    return $val;

}


