Subversion Repositories ORC

Rev

Rev 2 | Rev 9 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
## RollerCon support functions...
2
 
3
use strict;
4
use Exporter;
5
use CGI qw/:standard :netscape/;
6
use CGI::Cookie;
7
use DBI;
7 - 8
use WebDB;
2 - 9
 
7 - 10
 
11
my $dbh = WebDB->connect ();
2 - 12
our $ORCUSER;
7 - 13
use constant {
14
    USER   => 1,
15
    LEAD   => 2,
16
    MANAGER  => 3,
17
    DIRECTOR  => 4,
18
    ADMIN  => 5
19
  };
2 - 20
 
7 - 21
sub getAccessLevels {
22
  my %AccessLevels = (
23
    -1 => "Locked",
24
 
25
    1 => "Volunteer",
26
    2 => "Lead",
27
    3 => "Manager",
28
    4 => "Director",
29
    5 => "SysAdmin"
30
  );
31
  return \%AccessLevels;
32
}
33
 
2 - 34
sub authDB {
35
	my $src = shift;
36
	my $id = shift;
37
	my $pass = shift;
38
	my $level = shift;
39
	my ($result, $encpass);
40
 
41
	my $sth = $dbh->prepare("select * from official where email = ?");
42
	$sth->execute($id);
43
	my $RCDBIDHASH = $sth->fetchrow_hashref();
44
 
45
	if ($src eq "form") {
46
		my $pwdhan = $dbh->prepare("select password(?)");
47
		$pwdhan->execute($pass);
48
		($encpass) = $pwdhan->fetchrow();
49
	} else {
50
		$encpass = $pass;
51
	}
52
 
53
	if (!$RCDBIDHASH) {
54
		$result->{ERRMSG} = "User-ID/Email Address not found!";
55
		$result->{cookie_string} = '';
56
		$result->{RCid} = '';
57
		logit(0, "Account not found: $id");
58
		$result->{authenticated} = 'false';
59
	} elsif ($RCDBIDHASH->{'password'} ne $encpass) {
60
		$result->{ERRMSG} = "Incorrect Password!";
61
		$result->{cookie_string} = '';
62
		$result->{RCid} = $RCDBIDHASH->{'RCid'};
63
		logit($RCDBIDHASH->{'RCid'}, "Incorrect Password");
64
		$result->{authenticated} = 'false';
7 - 65
	} elsif (max ($RCDBIDHASH->{'access'}, values %{convertDepartments ($RCDBIDHASH->{department})}) < $level) {
66
	  if (getSetting ("MAINTENANCE")) {
67
	    $result->{ERRMSG} = "MAINTENANCE MODE: Logins are temporarily disabled.";
68
	  } else {
69
		  $result->{ERRMSG} = "Your account either needs to be activated, or doesn't have access to this page!";
70
  		logit($RCDBIDHASH->{'RCid'}, "Insufficient Privileges");
71
		}
2 - 72
		$result->{cookie_string} = "${id}&${encpass}&$RCDBIDHASH->{'access'}";
73
		$result->{RCid} = $RCDBIDHASH->{'RCid'};
74
		$result->{authenticated} = 'false';
75
	} else {
76
		$result->{ERRMSG} = '';
7 - 77
		$RCDBIDHASH->{department} = convertDepartments ($RCDBIDHASH->{department});
78
		$RCDBIDHASH->{'access'} = max ($RCDBIDHASH->{'access'}, values %{$RCDBIDHASH->{department}});
2 - 79
		$result->{cookie_string} = "${id}&${encpass}&$RCDBIDHASH->{'access'}";
80
		$result->{RCid} = $RCDBIDHASH->{'RCid'};
81
		logit($RCDBIDHASH->{'RCid'}, "Logged In") if $src eq "form";
7 - 82
		$dbh->do ("update official set last_login = now() where RCid = ?", undef, $RCDBIDHASH->{'RCid'}) if $src eq "form";
2 - 83
		$result->{authenticated} = 'true';
7 - 84
#		my @depts = map { s/-\d// } split /:/, $RCDBIDHASH->{department};
85
#		my @depts = split /:/, $RCDBIDHASH->{department};
86
 
2 - 87
		$ORCUSER=$RCDBIDHASH;
88
	}
89
	return $result;
90
}
91
 
7 - 92
sub max {
93
    my ($max, $next, @vars) = @_;
94
    return $max if not $next;
95
    return max( $max > $next ? $max : $next, @vars );
96
}
97
 
2 - 98
sub authenticate {									# Verifies the user has logged in or puts up a log in screen
7 - 99
	my $MAINTMODE = getSetting ("MAINTENANCE");
100
	my $MINLEVEL = $MAINTMODE ? $MAINTMODE : shift // 1;
101
 
2 - 102
	my ($ERRMSG, $authenticated, %FORM);
103
	my $sth = $dbh->prepare("select * from official where email = '?'");
104
 
105
	my $query = new CGI;
7 - 106
# Check to see if the user has already logged in (there should be cookies with their authentication)?
107
	my $RCAUTH = $query->cookie('RCAUTH');
2 - 108
	$FORM{'ID'} = $query->param('id') || '';
109
	$FORM{'PASS'} = $query->param('pass') || '';
110
	$FORM{'SUB'} = $query->param('login') || '';
111
 
112
	if ($FORM{'SUB'}) {
113
		#a log in form was submited
114
		if ($FORM{'SUB'} eq "Submit") {
115
			$authenticated = authDB('form', $FORM{'ID'}, $FORM{'PASS'}, $MINLEVEL);
116
		} elsif ($FORM{'SUB'} eq "New User") {
117
			# Print the new user form and exit
118
		}
119
	} elsif ($RCAUTH) {
120
		#We have an authenication cookie.  Double-check it
121
		my ($RCID, $RCPASS, $RCLVL) = split /&/, $RCAUTH;
122
		$authenticated = authDB('cookie', $RCID, $RCPASS, $MINLEVEL);
123
	} else {
124
		$authenticated->{authenticated} = 'false';
125
	}
126
 
127
 
128
	if ($authenticated->{authenticated} eq 'true') {
129
		return $authenticated->{cookie_string};
130
	}
131
 
132
 
133
 
134
# If we get here, the user has failed authentication; throw up the log-in screen and die.
135
 
136
	my $RCAUTH_cookie = CGI::Cookie->new(-name=>'RCAUTH',-value=>"",-expires=>"now");
137
 
138
if ($authenticated->{ERRMSG}) {
139
	$authenticated->{ERRMSG} = "<TR><TD colspan=2 align=center><font color=red><b>".$authenticated->{ERRMSG}."</b></font>&nbsp</TD></TR>";
140
	# Log the failed access attempt
141
} else {
142
	$authenticated->{ERRMSG} = "";
143
	# Since there was no ERRMSG, no need to log anything.
144
}
145
 
146
	print header(-cookie=>$RCAUTH_cookie);
147
	printRCHeader("Please Sign In");
148
	print<<authpage;
149
	<form action="$ENV{REQUEST_URI}" method=POST name=Req id=Req>
150
		<TR><TD colspan=2 align=center><b><font size=+2>Please Sign In</font>
7 - 151
		<TABLE>
2 - 152
		</TD></TR>
153
		<TR><TD colspan=2>&nbsp</TD></TR>
154
		$authenticated->{ERRMSG}
155
		<TR>
7 - 156
			<TD align=right><B>User ID:</TD><TD><INPUT type=text id=login name=id></TD>
2 - 157
		</TR>
158
		<TR>
159
			<TD align=right><B>Password:</TD><TD><INPUT type=password name=pass></TD>
160
		</TR>
161
		<TR><TD></TD><TD><INPUT type=submit name=login value=Submit></TD></TR>
162
		<TR><TD colspan=2 align=center>&nbsp;</TD></TR>
163
		<TR><TD colspan=2 align=center><A HREF="/schedule/manage_user.pl?submit=New%20User">[register as a new user]</A></TD></TR>
164
		<TR><TD colspan=2 align=center><A HREF="/schedule/password_reset.pl">[reset your password]</A></TD></TR>
165
	</TABLE>
166
	</FORM>
167
 
168
	<SCRIPT language="JavaScript">
169
	<!--
7 - 170
	document.getElementById("login").focus();
2 - 171
 
172
	function Login () {
173
		document.getElementById('Req').action = "$ENV{SCRIPT_NAME}";
174
		document.getElementById('Req').submit.click();
175
		return true;
176
	}
177
 
178
 
179
	//-->
180
	</SCRIPT>
181
 
182
authpage
183
 
184
#foreach (keys %ENV) {
185
#	print "$_: $ENV{$_}<br>";
186
#}
187
#	&JScript;
188
	exit;
189
}
190
 
7 - 191
sub getShiftDepartment {
192
  my $shiftID = shift // "";
193
  my $dept;
194
 
195
  if ($shiftID =~ /^\d+$/) {
196
    ($dept) = $dbh->selectrow_array ("select dept from shift where id = ?", undef, $shiftID);
197
  } elsif ($shiftID =~ /^\d+-ANN/) {
198
    $dept = "ANN";
199
  } else {
200
    $dept = "OFF";
201
  }
202
 
203
  return $dept;
204
}
205
 
206
sub getDepartments {
207
  my $RCid = shift // "";
208
  # If we get an RCid, return the list of departments and levels for that user.
209
  #   Otherwise (no parameter), return the list of departments with their display names.
210
 
211
	if ($RCid) {
212
  	my $sth = $dbh->prepare("select department from official where RCid = ?");
213
  	$sth->execute($RCid);
214
  	my ($dlist) = $sth->fetchrow;
215
  	return convertDepartments ($dlist);
216
	} else {
217
  	my %HASH;
218
  	my $sth = $dbh->prepare("select TLA, name from department");
219
  	$sth->execute();
220
  	while (my ($tla, $name) = $sth->fetchrow) {
221
  	  $HASH{$tla} = $name;
222
    }
223
    return \%HASH;
224
  }
225
 
226
}
227
 
228
sub convertDepartments {
229
  # For the department membership, converts the DB string back and forth to a hashref...
230
  my $input = shift // "";
231
  my $output;
232
 
233
  if (ref $input eq "HASH") {
234
    $output = join ":", map { $_."-".$input->{$_} } sort keys %{$input};
235
  } else {
236
  	foreach (split /:/, $input) {
237
  	  my ($tla, $level) = split /-/;
238
  	  $output->{$tla} = $level;
239
    }
240
  }
241
 
242
  return $output;
243
}
244
 
245
sub getSchedule {
246
  my $RCid = shift // return "ERROR: No RCid provided to getSchedule";
247
  my $filter = shift // "";
248
 
249
  my @whereclause;
250
  push @whereclause, "date >= date(now())" unless $filter eq "all";
251
#  if ($RCid ne $ORCUSER->{RCid}) {
252
#    push @whereclause, "dept != 'PER'";
253
#  }
254
 
255
  use DateTime;
256
  my $dt = DateTime->today;
257
  $dt =~ s/T00\:00\:00$//;
258
  my $now = DateTime->now;
259
 
260
 
261
  use HTML::Tiny;
262
  my $h = HTML::Tiny->new( mode => 'html' );
263
 
264
  my $where = scalar @whereclause ? "where ".join " and ", @whereclause : "";
265
  my @shifts;
266
  my $sth = $dbh->prepare("select * from (select id, date, dayofweek, track as location, time, role, teams, gtype, 'OFF' as dept, volhours from v_shift_officiating where RCid = ? union
267
                                          select id, date, dayofweek, track as location, time, role, teams, gtype, 'ANN' as dept, volhours from v_shift_announcer where RCid = ? union
268
                                          select id, date, dayofweek, location, time, role, '' as teams, type as gtype, dept, volhours from v_shift where RCid = ?) temp
269
                           $where order by date, time");
270
  $sth->execute($RCid, $RCid, $RCid);
271
  my $hours;
272
  while (my $s = $sth->fetchrow_hashref) {
273
    my ($yyyy, $mm, $dd) = split /\-/, $s->{date};
274
	  my $cutoff = DateTime->new(
275
        year => $yyyy,
276
        month => $mm,
277
        day => $dd,
278
        hour => 5,
279
        minute => 0,
280
        second => 0,
281
        time_zone => 'America/Los_Angeles'
282
    );
283
 
284
 
285
  	if (!$s->{teams}) {
286
  	  # it's a time-based shift
287
  	  if ($s->{dept} eq "PER") {
288
        if ($RCid eq $ORCUSER->{RCid}) {
289
          # DROP
290
  	      $s->{buttons} = $h->button ({ onClick=>"if (confirm('Really? You want to delete this personal time?')==true) { window.open('manage_personal_time.pl?choice=Delete&id=$s->{id}','Confirm Change','resizable,height=260,width=370'); return false; }" }, "DEL")."&nbsp;".$h->button ({ onClick=>"location.href='manage_personal_time.pl?choice=Update&id=$s->{id}'" }, "EDIT");
291
  	    } else {
292
  	      $s->{location} = "";
293
  	      $s->{role} = "";
294
  	    }
295
      } elsif (($RCid == $ORCUSER->{RCid} and $s->{gtype} !~ /^selected/ and $now < $cutoff) or ($ORCUSER->{department}->{$s->{dept}} >= 2 or $ORCUSER->{access} >= 5)) {
296
        # DROP
297
  		  $s->{buttons} = $h->button ({ onClick=>"if (confirm('Really? You want to drop this shift?')==true) { window.open('make_shift_change.pl?change=del&id=$s->{id}','Confirm Shift Change','resizable,height=260,width=370'); return false; }" }, "DROP");
298
	   		if ($ORCUSER->{department}->{$s->{dept}} >= 2 or $ORCUSER->{access} >= 5) {
299
   		    # NO SHOW
300
 	  	    $s->{buttons} .= "&nbsp;".$h->button ({ onClick=>"if (confirm('Really? They were a no show?')==true) { window.open('make_shift_change.pl?noshow=true&change=del&RCid=$RCid&id=$s->{id}','Confirm Shift Change','resizable,height=260,width=370'); return false; }" }, "NO SHOW");
301
 		    }
302
        $hours += $s->{volhours};
303
  		}
304
 
305
    } elsif (($RCid == $ORCUSER->{RCid} and $s->{gtype} !~ /^selected/ and $now < $cutoff) or ($ORCUSER->{department}->{$s->{dept}} >= 2 or $ORCUSER->{access} >= 5)) {
306
      # it's a game shift
307
      #DROP
308
  		$s->{buttons} = $h->button ({ onClick=>"if (confirm('Really? You want to drop this shift?')==true) { window.open('make_shift_change.pl?change=del&RCid=$RCid&id=$s->{id}&role=$s->{role}','Confirm Shift Change','resizable,height=260,width=370'); return false; }" }, "DROP");
309
   		if ($ORCUSER->{department}->{$s->{dept}} >= 2 or $ORCUSER->{access} >= 5) {
310
 		    # NO SHOW
311
        $s->{buttons} .= "&nbsp;".$h->button ({ onClick=>"if (confirm('Really? They were a no show?')==true) { window.open('make_shift_change.pl?noshow=true&change=del&RCid=$RCid&id=$s->{id}&role=$s->{role}','Confirm Shift Change','resizable,height=260,width=370'); return false; }" }, "NO SHOW");
312
      }
313
      $hours += $s->{volhours};
314
  	}
315
  	$s->{role} =~ s/\-\d$//;
316
 
317
  	push @shifts, $h->li ({ class=> $s->{date} eq $dt ? "nowrap highlighted" : "nowrap shaded" }, join '&nbsp;&nbsp;', $s->{date}, $s->{dayofweek}, $s->{time}, $s->{location}, getDepartments()->{$s->{dept}}, $s->{role}, $s->{teams}, $s->{buttons});
318
  }
319
 
320
  if (scalar @shifts) {
321
    return $h->ul ([ @shifts, $h->h5 ("Currently showing $hours hours of Volunteer Time.") ]);
322
  } else {
323
    return $h->p ({ class=>"hint" }, "[nothing scheduled at the moment]");
324
  }
325
}
326
 
2 - 327
sub getSetting {
328
	my $k = shift;
329
	my $sth = $dbh->prepare("select setting.value from setting where setting.key = ?");
330
	$sth->execute($k);
331
	return $sth->fetchrow_hashref()->{value};
332
}
333
 
334
sub getUser {
7 - 335
	my $ID = shift;
336
 
337
	my $sth;
338
	if ($ID =~ /^\d+$/) {
339
	  $sth = $dbh->prepare("select * from official where RCid = ?");
340
	} else {
341
	  $sth = $dbh->prepare("select * from official where email = ?");
342
  }
343
	$sth->execute($ID);
344
	return $sth->fetchrow_hashref;
2 - 345
}
346
 
347
sub getUserEmail {
348
	my $RCid = shift;
349
	my $sth = $dbh->prepare("select email from official where RCid = ?");
350
	$sth->execute($RCid);
351
	my ($email) = $sth->fetchrow_array();
352
	return $email;
353
}
354
 
355
sub getUserDerbyName {
356
	my $RCid = shift;
357
	my $sth = $dbh->prepare("select derby_name from official where RCid = ?");
358
	$sth->execute($RCid);
359
	my ($dname) = $sth->fetchrow_array();
360
	return $dname;
361
}
362
 
363
sub getYears {
7 - 364
#	my $sth = $dbh->prepare("select distinct year(date) from v_shift_admin_view union select year(now())");
365
	my $sth = $dbh->prepare("select distinct year(date) from v_shift_admin_view");
2 - 366
	$sth->execute();
367
	my @years;
368
	while (my ($y) =$sth->fetchrow_array()) { push @years, $y; }
369
	return \@years;
370
}
371
 
372
sub printRCHeader {
373
	my $PAGE_TITLE = shift;
7 - 374
	use CGI qw/start_html/;
375
	use HTML::Tiny;
376
  my $h = HTML::Tiny->new( mode => 'html' );
2 - 377
 
7 - 378
#  my $logout = $h->a ({ href=>"index.pl", onClick=>"document.cookie = 'RCAUTH=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/';return true;" }, "[Log Out]");
379
my $logout = $h->button ({ onClick=>"document.cookie = 'RCAUTH=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/'; location.href='/';" }, "Log Out");
380
	my $loggedinas = $ORCUSER ? "Currently logged in as: ".$h->a ({ href=>"/schedule/manage_user.pl?submit=View&RCid=$ORCUSER->{RCid}" }, $ORCUSER->{derby_name})." $logout" : "";
381
 
382
  print start_html (-title=>"vORC - $PAGE_TITLE", -style => {'src' => "/style.css"} );
383
 
384
#<html><head><title>Officials' RollerCon Schedule Manager - $PAGE_TITLE</title>
385
#<link rel="stylesheet" type="text/css" href="/style.css">
386
#</head>
387
#<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#551A8B" alink="#FF0000">
388
	print $h->div ({ class=>"sp0" }, [ $h->div ({ class=>"spLeft" },  $h->a ({ href=>"/schedule/" }, $h->img ({ src=>"/logo.jpg", width=>"75", height=>"75" }))),
389
	                                   $h->div ({ class=>"spRight" }, [ $h->h1 (["vORC $PAGE_TITLE", $h->br]),
390
	                                   $loggedinas,
391
	                                   ])
392
	                                 ]);
393
#print<<rcheader;
394
#  <TABLE>
395
#	<TR class="nostripe">
396
#		<TD align=right><img SRC="/logo.jpg"></TD>
397
#		<TD align=center valign=middle><b><font size=+3>Officials' RollerCon<br>Schedule Manager<br>$PAGE_TITLE</FONT></b>
398
#	<p align=right><font size=-2>$loggedinas <a href='index.pl' onClick="document.cookie = 'RCAUTH=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/';return true;">[Log Out]</a></font></TD>
399
#	</TR>
2 - 400
 
7 - 401
#rcheader
2 - 402
}
403
 
404
sub changeShift {
7 - 405
	my ($change, $shift_id, $role, $user_id) = @_;
406
	my $leadership_change = 0;
407
	my $department = getShiftDepartment ($role ? $shift_id."-".$role : $shift_id);
408
	my $game_based = $role ? "game" : "shift";
409
	my $sth;
2 - 410
 
7 - 411
	if ($change eq "add") {
412
  	my $taken;
413
  	if ($game_based eq "game") {
414
  	  ($taken) = $dbh->selectrow_array ("select count(*) from assignment where Gid = ? and role = ?", undef, $shift_id, $role);
415
  	} else {
416
  	  ($taken) = $dbh->selectrow_array ("select count(*) from shift where id = ? and isnull(assignee_id) = 0", undef, $shift_id);
417
  	}
418
  	if ($taken) {
419
  	    return "<br>Denied! This shift is already taken ($shift_id).<br>\n";
420
  	}
421
  }
2 - 422
 
7 - 423
	if (lc ($user_id) ne lc ($ORCUSER->{RCid})) { # they're changing someone else's schedule...
424
	  if ($ORCUSER->{department}->{$department} >= 2 or $ORCUSER->{access} >= 5) {
425
	    # the user making the change is either a lead in the dept or a sysadmin
426
	    logit ($ORCUSER->{RCid}, "$ORCUSER->{derby_name} changed someone else's schedule. ($change, $shift_id, $role, $user_id)");
427
	    logit ($user_id, "Schedule was changed by $ORCUSER->{derby_name}. ($change, $shift_id, $role, $user_id)");
428
	    $leadership_change = 1;
2 - 429
	  } else {
7 - 430
	    logit ($ORCUSER->{RCid}, "Unauthorized attempt to change someone else's schedule. ($change, $shift_id, $role, $user_id)");
431
	    return "<br>Denied! You are not authorized to change someone else's schedule in this department ($department).<br>\n";
2 - 432
	  }
7 - 433
	} elsif ($ORCUSER->{department}->{$department} >= 3) {
434
	  # Managers can sign up for as many shifts within their own department as they like...
435
	  $leadership_change = 1;
2 - 436
	}
437
 
7 - 438
  if ($change eq "add" and convertDepartments(getUser($user_id)->{department})->{$department} < 1) {
439
		return "<br>Denied! User ($user_id) is not a member of Department ($department)!<br>\n";
440
  }
441
 
442
  if ($change eq "add" and findConflict ($user_id, $shift_id, $game_based)) {
443
		return "<br>Denied! There is a conflict with that shift's time!<br>\n";
444
  }
445
 
446
 	my ($game_type) = $dbh->selectrow_array ("select type from ".$game_based." where id = ?", undef, $shift_id);
447
 	if ($game_type =~ /^selected/ and !$leadership_change) {
448
 	  return "<br>Denied! Only leadership can make changes to 'selected staffing' shifts!<br>\n";
449
 	}
450
 
451
 	if ($change eq "add" and $game_type eq "lead" and convertDepartments(getUser($user_id)->{department})->{$department} < 2 and $ORCUSER->{access} < 3) {
452
 	  return "<br>Denied! Shift reserved for leadership staff!<br>\n";
453
 	}
454
 
455
 	my $MAXSHIFTS = getSetting ("MAX_SHIFT_SIGNUP_PER_DAY");
456
 	my $daily_count = signUpCount ('get', $user_id);
457
 	if ($change eq "add" and $daily_count >= $MAXSHIFTS and !$leadership_change) {
458
 		return "<br>Denied! You may only sign up for $MAXSHIFTS $game_type shifts in one day!<br>\n";
459
 	}
460
 
461
 	my @DBARGS;
462
  if ($game_based eq "game") {
463
  	if ($change eq "add") {
464
  		$sth = $dbh->prepare("insert into assignment (Gid, role, RCid) values (?, ?, ?)");
465
  	} elsif ($change eq "del") {
466
  		$sth = $dbh->prepare("delete from assignment where Gid = ? and role = ? and RCid= ?");
467
  	}
468
  	@DBARGS = ($shift_id, $role, $user_id);
469
  } else {
470
  	if ($change eq "add") {
471
  		$sth = $dbh->prepare("update shift set assignee_id = ? where id = ?");
472
  		@DBARGS = ($user_id, $shift_id);
473
  	} elsif ($change eq "del") {
474
  		$sth = $dbh->prepare("update shift set assignee_id = null where id = ?");
475
  		@DBARGS = ($shift_id);
476
  	}
477
  }
478
 
479
  print "<br>attempting to make DB changes...<br>";
480
  if ($sth->execute (@DBARGS)) {
481
  	$daily_count = signUpCount ($change, $user_id) unless $leadership_change;
482
  	logit ($user_id, "Shift ".ucfirst($change).": $shift_id -> $role");
483
  	print "Success!...<br>You've signed up for $daily_count shifts today (you're currently allowed to sign up for $MAXSHIFTS per day).<br>\n";
484
  	return;
485
  } else {
486
    return "<br><b>You did not get the shift</b>, most likely because someone else took it while you were looking.<br>\nERROR: ", $sth->errstr();
487
  }
488
}
489
 
490
sub modShiftTime {
491
	my ($shift_id, $user_id, $diff) = @_;
492
	my $ORCUSER = getUser (1);
2 - 493
 
7 - 494
	use Scalar::Util qw(looks_like_number);
495
	if (!looks_like_number ($diff)) {
496
	  print "<br>ERROR! The time adjustment ($diff) doesn't look like a number.<br>\n";
497
  	return;
2 - 498
	}
499
 
7 - 500
  my ($validate_assignee) = $dbh->selectrow_array ("select count(*) from v_shift where id = ? and RCid = ?", undef, $shift_id, $user_id);
501
 	if (!$validate_assignee) {
502
	  print "<br>ERROR! This shift is assigned to someone else.<br>\n";
503
  	return;
504
 	}
505
 
506
	my $department = getShiftDepartment ($shift_id);
507
  if (convertDepartments ($ORCUSER->{department})->{$department} < 2 and $ORCUSER->{access} < 5) {
508
	  print "<br>ERROR! You're not authorized to modify this shift's time.<br>\n";
509
	  logit ($ORCUSER->{RCid}, "Unauthorized attempt to modify shift time. ($department, $shift_id)");
510
  	return;
511
 	}
512
 
513
  my $rows_changed;
514
  print "<br>attempting to make DB changes...<br>";
515
  if ($diff == 0) {
516
	  $rows_changed = $dbh->do ("update shift set mod_time = null where id = ? and assignee_id = ?", undef, $shift_id, $user_id);
517
  } else {
518
	  $rows_changed = $dbh->do ("update shift set mod_time = ? where id = ? and assignee_id = ?", undef, $diff, $shift_id, $user_id);
519
  }
520
 
521
 
522
  if (!$rows_changed or $dbh->errstr) {
523
  	print "ERROR: Nothing got updated".$dbh->errstr;
524
  	logit (0, "ERROR modifying a shift time ($diff, $shift_id, $user_id):".$dbh->errstr);
525
  } else {
526
  	print "SUCCESS: Shift $shift_id succesfully modified by $diff hour(s)";
527
  	logit ($ORCUSER->{RCid}, "SUCCESS: Shift $shift_id succesfully modified by $diff hour(s)");
528
 
529
  }
530
  return;
2 - 531
}
532
 
533
sub signUpCount {
534
	my $action = shift;
535
	my $id = shift;
536
	my $gtype = shift // "";
537
 
7 - 538
	if ($id eq $ORCUSER->{RCid}) {
2 - 539
		if ($action eq 'add') {
7 - 540
			if (signUpCount ('get', $id)) {
541
				$dbh->do("update sign_up_count set sign_ups = sign_ups + 1 where date = curdate() and RCid = ?", undef, $id);
2 - 542
			} else {
7 - 543
				$dbh->do("replace into sign_up_count values (curdate(), ?, 1)", undef, $id);
2 - 544
			}
545
		} elsif ($action eq 'del') {
7 - 546
			if (signUpCount ('get', $id)) {
547
				$dbh->do("update sign_up_count set sign_ups = sign_ups - 1 where date = curdate() and RCid = ?", undef, $id);
2 - 548
			}
549
		}
550
	}
551
 
7 - 552
	my ($R) = $dbh->selectrow_array ("select sign_ups from sign_up_count where RCid = ? and date = curdate()", undef, $id);
2 - 553
 
554
	return $R ? $R : '0';
555
}
556
 
557
sub signUpEligible {
558
	my $user = shift;
559
	my $t = shift;
7 - 560
	my $shifttype = shift // "game";
2 - 561
 
7 - 562
	if (findConflict ($user->{RCid}, $t->{id}, $shifttype)) { return 0; }
563
 
2 - 564
	if (!exists $user->{sign_ups_today}) {
565
		$user->{sign_ups_today} = signUpCount('get', $user->{RCid});
566
	}
567
 
7 - 568
	if ($shifttype eq "game") {
569
    if ($t->{gtype} !~ /^selected/ and $t->{gtype} ne "short track" and $user->{sign_ups_today} < getSetting("MAX_SHIFT_SIGNUP_PER_DAY")) {
2 - 570
			return 1;
571
		} else {
572
			return 0;
573
		}
7 - 574
	} else {
575
	  if ($user->{department}->{$t->{dept}} < 1) { return 0; }
576
	  if ($t->{type} eq "lead" and $user->{department}->{$t->{dept}} < 2) { return 0; }
577
	  if ($t->{type} eq "manager" and $user->{department}->{$t->{dept}} < 3) { return 0; }
578
    if ($t->{type} !~ /^selected/ and $user->{sign_ups_today} < getSetting("MAX_SHIFT_SIGNUP_PER_DAY")) {
2 - 579
			return 1;
580
		} else {
581
			return 0;
582
		}
583
	}
584
}
585
 
586
sub findConflict {
587
  my $rcid = shift;
588
  my $gid = shift;
7 - 589
  my $type = shift // "";
590
  my ($date, $start, $end, $conflicts);
2 - 591
 
7 - 592
  if ($type eq "game") {
593
  # Are they already signed up for this game? (It's faster to check the two views one at a time...)
594
#    ($conflicts) = $dbh->selectrow_array ("select count(*) from v_shift_officiating where substring_index(id, '-', 1) = ? and RCid = ?", undef, $gid, $rcid);
595
    ($conflicts) = $dbh->selectrow_array ("select count(*) from v_shift_officiating where id = ? and RCid = ?", undef, $gid, $rcid);
596
  	if ($conflicts) { return 1; } # no need to keep looking...
597
    ($conflicts) = $dbh->selectrow_array ("select count(*) from v_shift_announcer where id = ? and RCid = ?", undef, $gid, $rcid);
598
  	if ($conflicts) { return 1; } # no need to keep looking...
599
 
600
    ($date, $start, $end) = $dbh->selectrow_array ("select distinct date, time, end_time from game where id = ?", undef, $gid);
601
  } elsif ($type eq "personal")  {
602
    ($date, $start, $end) = @{ $gid };
603
  } else {
604
    ($date, $start, $end) = $dbh->selectrow_array ("select distinct date, start_time, end_time from shift where id = ?", undef, $gid);
605
  }
2 - 606
 
607
  # Are they signed up for any games that would conflict with this one?
7 - 608
#  my $sth = $dbh->prepare("select count(*) from v_shift_admin_view where id in (select id from game where date = (select date from game where id = ?) and ((time <= (select time from game where id = ?) and end_time > (select time from game where id = ?)) or (time > (select time from game where id = ?) and time < (select end_time from game where id = ?)))) and RCid = ?");
609
#  my $sth = $dbh->prepare("select count(*) from v_shift_all where id in (select id from v_shift_all where date = (select date from v_shift_all where id = ?) and ((start_time <= (select start_time from v_shift_all where id = ?) and end_time > (select start_time from v_shift_all where id = ?)) or (start_time > (select start_time from v_shift_all where id = ?) and start_time < (select end_time from v_shift_all where id = ?)))) and RCid = ?");
2 - 610
 
7 - 611
  ($conflicts) = $dbh->selectrow_array ("select count(*) from (
612
    select id from v_shift             where date = ? and ((start_time <= ? and end_time > ?) or (start_time > ? and start_time < ?)) and RCid = ? union
613
    select id from v_shift_announcer   where date = ? and ((start_time <= ? and end_time > ?) or (start_time > ? and start_time < ?)) and RCid = ? union
614
    select id from v_shift_officiating where date = ? and ((start_time <= ? and end_time > ?) or (start_time > ? and start_time < ?)) and RCid = ? ) alltables",
615
    undef, $date, $start, $start, $start, $end, $rcid, $date, $start, $start, $start, $end, $rcid, $date, $start, $start, $start, $end, $rcid
616
  );
617
 
2 - 618
  return $conflicts;
619
}
620
 
621
sub changeLeadShift {
622
	my ($change, $lshift, $user_id) = @_;
623
	my $ERRMSG;
624
 
625
	my $sth = $dbh->prepare("update lead_shift set assignee_id = ? where id = ?");
626
 
627
	print "<br>attempting to make DB changes...<br>";
628
	if ($change eq "add") {
629
		$sth->execute($user_id, $lshift)
630
    	or $ERRMSG = "ERROR: Can't execute SQL statement: ".$sth->errstr()."\n";
631
	} elsif ($change eq "del") {
632
		$sth->execute('', $lshift)
633
    	or $ERRMSG = "ERROR: Can't execute SQL statement: ".$sth->errstr()."\n";
634
	}
635
	if ($ERRMSG) {
636
		print $ERRMSG;
637
	} else {
638
		logit($user_id, "Lead Shift ".ucfirst($change).": $lshift");
639
  	print "Success.<br>";
640
  }
641
}
642
 
643
sub logit {
644
	my $RCid = shift;
645
	my $msg = shift;
646
	my $sth = $dbh->prepare("insert into log (RCid, event) values (?, ?)");
647
	$sth->execute($RCid, $msg);
648
}
649
 
650
1;