"); }
my $options = ['', @$teacher_ids];
if ($static_booker) {
unshift @$options, $static_booker;
}
if (!$mine && $id ne $static_booker) {
unshift @$options, $id;
}
my $abbrev;
@$options = map { $_, $_ eq "" ? "" : "$_ $teacher_names->{$_}" } @$options; $abbrev = 1;
# @$options = map { $_, $_ eq "" ? "" : $teacher_names->{$_} || $_ } @$options; $abbrev = 1;
my $tiny = $booker eq "";
my $size = 7;
my $mangle_factor = $screenwidth < 1024 ? 1 : 1.6;
$size *= $mangle_factor;
my $dropdown_opts = {
no_prompt=>1, abbrev=>$abbrev, selected=>$booker||'',
clip=>1, size=>$size, #$class ? 8 : 4, # COMPACTING
# enter_submits => 1,
# dynamic_expand=>1,
};
# out(qq{ }.dropdown($dropdown_opts, $cell_name, $options).qq{ });
out(fancy_select($dropdown_opts, $cell_name, $options));
} else {
checkbox_selector();
}
}
sub hdr_ {
# make sure we are in the "calendar" window using javascript - if not, we open a new window.
hdr(@_);
# this is disabled at the moment because it causes more problems than it's worth to get rid of the scrollbars
# out(<
#if (window.name != "calendar") {
# fsoinw_window = open(window.location, "calendar", 'width='+(screen.width-10)+',height='+(screen.height-80)+',screenX=0,screenY=0,left=0,top=0,resizable=1');
#
# this.focus();
# self.opener=this;
# self.close();
#}
#
#End
}
sub ftr_ {
# make sure we are in the "calendar" window using javascript - if not, we logout. yuk
ftr("@_");
# ftr(<
#if (window.name != "calendar") {
# GetFormField("logout").click();
#}
#
#End
}
# ---- here be stuff to do with borrowing laptops... :)
sub laptops {
# this exapands numeric abbreviations in the laptop names list
my $laptops_abbrv = $conf->{laptops}{__order};
my $laptops = [];
for (@$laptops_abbrv) {
if ($_ =~ /^(?:(.*? +))?(\d+)-(\d+)$/) {
my ($text, $from, $to) = ($1, $2, $3);
$text ||= "";
for my $i ($from .. $to) {
push @$laptops, "$text$i";
}
} else {
push @$laptops, $_;
}
}
return $laptops;
}
sub page_laptops {
hdr_(title => "Borrow Laptops", bg_color => $body_bgcolor, fg_color => $body_textcolor, link_color => $body_linkcolor);
but("back");
space(2);
but("logout");
nl(); nl();
out(p(<{$_}, $_} keys %$student_names_by_id};
$student_names = [sort values %$student_names_by_id];
if (param("borrow")) {
if (param("laptop") && param("student_borrow")) {
borrow_laptop(param("laptop"), param("student_borrow"));
} else {
redmsg("You didn't select a student and a laptop."); nl();
}
}
if (param("return")) {
if (param("student_return")) {
return_laptop(param("student_return"));
} else {
redmsg("You didn't select a student."); nl();
}
}
get_laptops_available();
my $options;
my $options_borrow = [];
my $options_return = [];
for my $student_name (@$student_names) {
my $student_id = $student_ids_by_name->{$student_name};
if ($laptops_borrowed_by_student->{$student_id}) {
push @$options_return, $student_id, $student_name;
} else {
push @$options_borrow, $student_id, $student_name;
}
}
if (@$options_borrow) {
out(dropdown({prompt=>"student...", abbrev=>1}, "student_borrow", $options_borrow));
space(2);
out(dropdown({prompt=>"laptop..."}, "laptop", $laptops_available));
space(2);
but("borrow");
nl(); nl();
}
if (@$options_return) {
out(dropdown({prompt=>"student...", abbrev=>1, onchange=>'laptop_student_return_selected()'}, "student_return", $options_return));
space(2);
but("return", "return");
}
nl();
nl();
nl();
nl();
out(h2("Currently on Loan:"));
if (@$laptops_data) {
Tag("table", id=>"scrolltable", cellspacing=>4);
Tag("thead");
print join "", map {"$_ | | "} ("date borrowed", "laptop", "student id", "student name", "teacher id");
Ctag("thead");
for (@$laptops_data) {
my ($date, $laptop, $student_id, $student_name, $teacher_id) = @$_;
$date =~ s/^(\d{4})(\d{2})(\d{2})$/$1.$2.$3/;
$date =~ s/\.0/./g;
print "";
print join "", map {"$_ | | "} $date, $laptop, $student_id, $student_name, $teacher_id;
print " \n";
}
Ctag("table");
} else {
msg("There are no laptops on loan at the moment.");
}
}
sub get_laptops_available {
$laptops_borrowed = {};
$laptops_borrowed_by_student = {};
for (@$laptops_data) {
my ($date, $laptop, $student_id, $student_name, $teacher_id) = @$_;
$laptops_borrowed->{$laptop} = $student_id;
$laptops_borrowed_by_student->{$student_id} = $laptop;
}
$laptops_available = [grep {!$laptops_borrowed->{$_}} @$laptops];
}
sub borrow_laptop {
my ($laptop, $student_id) = @_;
my $student_name = $student_names_by_id->{$student_id};
# check the laptop is valid and not already borrowed,
my $ok = 0;
for (@$laptops_available) {
if ($laptop eq $_) { $ok = 1; }
}
if (!$ok) {
redmsg("This laptop `$laptop' has already been borrowed."); nl();
return;
}
# check if the student has already borrowed a laptop
for (@$laptops_data) {
my ($date, $_laptop, $_student_id, $_student_name, $teacher_id) = @$_;
if ($student_id eq $_student_id) {
redmsg("This student `$student_name' has already borrowed a laptop `$_laptop' and has not returned it yet."); nl();
return;
}
}
# check the student is a valid student!
if (!exists $student_names_by_id->{$student_id}) {
redmsg("This student id `$student_id' does not exist in the active directory!"); nl();
return;
}
my $ymd = $today_date->yyyymmdd;
append_tsv_row($laptops_log_file, [$ymd, "borrow", $laptop, $student_id, $student_name, $id]);
push @$laptops_data, [$ymd, $laptop, $student_id, $student_name, $id];
save_laptops();
msg("`$student_name' has borrowed `$laptop'."); nl();
}
sub return_laptop {
my ($student_id) = @_;
my $student_name = $student_names_by_id->{$student_id};
my $laptops_data_new = [];
my $done;
for my $row (reverse @$laptops_data) { # paranoia ;)
my ($date, $laptop, $_student_id, $_student_name, $teacher_id) = @$row;
if (!$done && $student_id eq $_student_id) {
msg("`$student_name' has returned the laptop `$laptop'."); nl();
$done = 1;
append_tsv_row($laptops_log_file, [$date, "return", $laptop, $_student_id, $_student_name, $id]);
} else {
push @$laptops_data_new, $row;
}
}
if ($done) {
$laptops_data = $laptops_data_new;
save_laptops();
} else {
redmsg("`$student_name' had not borrowed a laptop."); nl();
}
}
sub append_tsv_row {
my ($file, $row) = @_;
my $fh = IO::File->new($file, "a") ||
die "can't open file `$file' to append: $!";
binmode($fh);
print $fh join("\t", @$row), "\n";
close $fh;
}
sub lookup_laptop_borrowers {
my %long_uid_of;
my %names;
my @short_uids;
my $dup_uids;
# die Dumper($ou_allowed);
my @domains = @{ou_allowed_tree_to_ldap_domains($conf->{"ou.allowed.laptops"})};
for my $domain (@domains) {
my $users = ldap_lookup_users_uid_name($domain);
if (ref $users) {
USER: for my $user (@$users) {
my $long_uid = $user->{uid};
my $short_uid = uc_or_lc_id($user->{short_uid});
if (!defined $short_uid or $short_uid eq "") {
# msg("no short_uid ($short_uid_type) for $long_uid");
next USER;
}
if (exists $long_uid_of{$short_uid}) {
msg("duplicate short_uid `$short_uid' ($short_uid_type): for $long_uid_of{$short_uid}, $long_uid");
$dup_uids = 1;
} else {
$long_uid_of{$short_uid} = $long_uid;
}
push @short_uids, $short_uid; # for dropdown
my ($name1, $name2) = ldap_get_name($user);
$name2 = uc($name2); # if $conf->{surname_uppercase};
my $fullname = "";
if ($name1 and $name2) { $fullname = "$name2 $name1"; }
$names{$short_uid} = $fullname;
}
} else {
die "bad: ldap_lookup in domain $domain returned $users";
}
}
if ($dup_uids) {
die "duplicate short_uids - please contact $conf->{administrator}";
}
@short_uids = sort @short_uids;
return (\%names, \@short_uids);
}
sub load_laptops {
$laptops_data = read_tsv($laptops_file, 1);
fix_caps_ids($laptops_data, [2, 4]);
}
sub save_laptops {
write_tsv_and_backup($laptops_file, $laptops_data);
}
# timetable update stuff ----------------------------
sub update_timetable_from_first_class {
make_recovery_backup();
load_calendar_data();
sql_connect();
# ldap_connect();
my ($teacher_names, $teacher_ids, $rooms, $room, $timetable);
my ($conf);
my $bookings_conf_file = "bookings.conf";
$conf = read_data($bookings_conf_file);
($teacher_names, $teacher_ids) = lookup_staff_etc();
my $teacher_id_by_name = {};
while (my ($id, $name) = each %$teacher_names) {
$teacher_id_by_name->{uc($name)} = $id;
}
# check_teacher_names();
my $room_resources = room_resources();
# ($days) = sql_col("SELECT Name FROM tblDay WHERE deleted=0 ORDER BY SortOrder");
# ($periods) = sql_col("SELECT Name FROM tblPeriod WHERE deleted=0 ORDER BY SortOrder");
my $index = {};
for my $room_resource (@$room_resources) {
my ($room, $resource) = @$room_resource;
$index->{$resource} = $room;
}
@$static = grep {
my $resource_full = $_->[2];
!$index->{$resource_full};
} @$static;
@$static_info = grep {
my $resource_full = $_->[2];
!$index->{$resource_full};
} @$static_info;
Tag("div", style=>"overflow: auto; height: 200px;");
msg("Updating the timetable from the first-class database. Please read all the messages - you may need to scroll down.");
nl();
for my $room_resource (@$room_resources) {
my ($room, $resource) = @$room_resource;
$timetable = room_timetable($room);
if (!@$timetable) {
msg("Room `$room' is apparently not in the timetable database.");
} else {
msg("Updating timetable for room `$room' ($resource).");
}
for (@$timetable) {
my ($subject, $day, $period, $room, $firstname, $familyname, $form) = @$_;
if ($period !~ /period/i) { next; } # e.g. Home Group
my $fullname = uc("$firstname $familyname");
my ($id) = $teacher_id_by_name->{$fullname};
if (!$id) {
redmsg("teacher `$fullname' is not in the directory with that name, please fix this.\n");
}
else {
push @$static, [$day, $period, $resource, $id];
# print join "\t", $day, $period, $resource, lc($id);
# print " "; # DEBUG
# print "-- ", join "\t", @$_;
# print " "; # DEBUG
# print "\n";
}
}
}
# get the indexes for the tables,
# for scan_all_bookings_for_any_that_conflict_with_changed_timetable
$static_x = table_to_index($static);
$static_info_x = table_to_index($static_info);
$changed_static = 1;
$changed_static_info = 1;
scan_all_bookings_for_any_that_conflict_with_changed_timetable();
Ctag("div");
nl();
write_files_if_necessary();
}
#display_timetable($timetable);
#sub check_teacher_names {
# my $tt_names = timetable_teacher_names();
# my $errors = 0;
# for (@$tt_names) {
# my ($firstname, $familyname) = @$_;
# my $fullname = uc("$firstname $familyname");
# my ($id) = $teacher_id_by_name->{$fullname};
# if (!$id) {
# print STDERR "teacher `$fullname' in the timetable is not in the directory with that name.\n"; $errors = 1;
# $errors = 1;
# }
# }
# if ($errors) {
# die "please fix this inconsistency\n";
# }
#}
sub timetable_teacher_names {
my ($names) = sql_rows(<{resources}{__order}}) {
for my $res (@{$conf->{resources}{$cat}{__order}}) {
my $res_full = "$cat : $res";
if ($res_full =~ /\b(rm|room)s?\b/i) {
my $code = $res_full;
$code =~ s/: \.$//;
$code =~ s/.* //;
push @$room_resources, [$code, $res_full];
}
}
}
return $room_resources;
}
sub date_init {
$today_date = Date->today;
# date
$today_wday = $today_date->{wday}-2;
$today_wday = 6 if $today_wday == -1; # count sunday == 6, monday == 0
$monday1 = $today_date->dup;
$monday1->back_days($today_wday); # go to monday (day 2, counting from 1->sun)
}
sub allow_to_book_lunch {
return conf_by_category_or_default("allow_to_book_lunch");
}
sub allow_to_book_holidays {
return conf_by_category_or_default("allow_to_book_holidays");
}
sub allow_to_book_evenings {
return conf_by_category_or_default("allow_to_book_evenings");
}
sub allow_to_book_periods {
return conf_by_category_or_default("allow_to_book_periods");
}
sub conf_by_category_or_default {
my ($which) = @_;
$category ||= param("category");
my $allow;
if (ref $conf->{$which}) {
$allow = $conf->{$which}{$category};
if (!defined $allow) { $allow = $conf->{$which}{default} || 0 }
} else {
$allow = $conf->{$which} || 0;
}
# print "$which $category $allow ";
return $allow;
}
sub is_holiday_week {
my ($date_monday) = @_;
my $date1 = $date_monday->dup;
my $wday = 0;
while ($wday <= $max_wday) {
# print "-", $date1->ymd2, " ";
if (!is_holiday($date1)) {
# print "is_holiday_week : no \n";
return 0;
}
++$wday;
$date1->tomorrow();
}
# print "is_holiday_week : yes \n";
return is_holiday($date_monday);
}
sub increase_n_weeks_to_allow_for_holidays {
my $count = $n_weeks;
my $monday = $monday1->dup;
while ($count) {
# print $monday->ymd2, " ";
if (is_holiday_week($monday)) {
$n_weeks++;
} else {
--$count;
}
$monday->forward_days(7);
}
}
|