[Ils-source] r1410 - in branches/1.6: . db/mssql src/com/resolutions/ils/data src/com/resolutions/jobs webapp webapp/WEB-INF/classes webapp/WEB-INF/lib

scribe at crosswire.org scribe at crosswire.org
Thu Mar 10 11:44:42 MST 2016


Author: scribe
Date: 2016-03-10 11:44:41 -0700 (Thu, 10 Mar 2016)
New Revision: 1410

Added:
   branches/1.6/db/mssql/upgrade1.80.5-1.sql
   branches/1.6/db/mssql/upgrade185.1.sql
   branches/1.6/src/com/resolutions/jobs/MgrRecurEMails.java
   branches/1.6/webapp/report_recurrent_training.jsp
Modified:
   branches/1.6/
   branches/1.6/db/mssql/ilsdb.sql
   branches/1.6/src/com/resolutions/ils/data/Group.java
   branches/1.6/src/com/resolutions/ils/data/UserProfile.java
   branches/1.6/webapp/WEB-INF/classes/jobs.xml
   branches/1.6/webapp/WEB-INF/lib/crosswire-integration.jar
   branches/1.6/webapp/WEB-INF/lib/ils.jar
   branches/1.6/webapp/admin_groupmanagement.jsp
   branches/1.6/webapp/admin_profile.jsp
   branches/1.6/webapp/admin_studentrecords.jsp
   branches/1.6/webapp/admin_systemmanagement.jsp
   branches/1.6/webapp/menu.jsp
   branches/1.6/webapp/report_pending_summary.jsp
Log:
preparing for release of 1.80.5



Property changes on: branches/1.6
___________________________________________________________________
Modified: svn:mergeinfo
   - /trunk:796-1303,1306-1307,1309-1311,1319-1320,1322-1323,1325,1328-1330,1332,1334-1335,1337,1339,1349-1355,1360-1365,1380-1383,1391,1393,1402-1404
   + /trunk:796-1303,1306-1307,1309-1311,1319-1320,1322-1323,1325,1328-1330,1332,1334-1335,1337,1339,1349-1356,1359-1365,1369,1373-1374,1380-1383,1391,1393,1402-1404,1409

Modified: branches/1.6/db/mssql/ilsdb.sql
===================================================================
--- branches/1.6/db/mssql/ilsdb.sql	2016-03-10 18:38:22 UTC (rev 1409)
+++ branches/1.6/db/mssql/ilsdb.sql	2016-03-10 18:44:41 UTC (rev 1410)
@@ -1,7 +1,7 @@
 CREATE TABLE ILSGROUP (COMPANYID INTEGER NOT NULL, ILSGROUPID INTEGER IDENTITY(1,1) NOT NULL, GROUPNAME VARCHAR(75) NOT NULL, GROUPDESC VARCHAR(255), GROUPTYPEID INTEGER, USERDATA VARCHAR(80), CONSTRAINT ILSGROUPPK1 PRIMARY KEY (COMPANYID, ILSGROUPID))
-CREATE TABLE COURSE (COMPANYID INTEGER NOT NULL, COURSID INTEGER IDENTITY(1,1) NOT NULL, COURSNUM VARCHAR(20) NOT NULL, COURSNAME VARCHAR(100), COURSDESC VARCHAR(500), COURSTYPEID INTEGER, COURSPASS INTEGER, COURSPASSEXPDAYS INTEGER, COURSREASBEFDAYS INTEGER, COURSURL VARCHAR(255), COURSCKLISTURL VARCHAR(255), COURSCOST FLOAT, COURSSEATMINS INTEGER, COURSISCURRICULUM CHAR(1), COURSISQUICKVIEW CHAR(1), COURSPOSTDATE DATETIME, COURSISACTIVE CHAR(1), COURSISIPRESTRICTED char(1), COURSREQMGRAPPRVL CHAR(1), USERDATA VARCHAR(80), COURSISCURRICCERT char(1) default 'F', CONSTRAINT COURSEPK1 PRIMARY KEY (COMPANYID, COURSID))
+CREATE TABLE COURSE (COMPANYID INTEGER NOT NULL, COURSID INTEGER IDENTITY(1,1) NOT NULL, COURSNUM VARCHAR(20) NOT NULL, COURSNAME VARCHAR(100), COURSDESC VARCHAR(500), COURSTYPEID INTEGER, COURSPASS INTEGER, COURSPASSEXPDAYS INTEGER, COURSREASBEFDAYS INTEGER, COURSURL VARCHAR(255), COURSCKLISTURL VARCHAR(255), COURSCOST FLOAT, COURSSEATMINS INTEGER, COURSISCURRICULUM CHAR(1), COURSISQUICKVIEW CHAR(1), COURSPOSTDATE DATETIME, COURSISACTIVE CHAR(1), COURSISIPRESTRICTED char(1), COURSREQMGRAPPRVL CHAR(1), USERDATA VARCHAR(80), COURSISCURRICCERT char(1) DEFAULT 'F', CONSTRAINT COURSEPK1 PRIMARY KEY (COMPANYID, COURSID))
 
-CREATE TABLE USERPROFILE (COMPANYID INTEGER NOT NULL, USERPRID INTEGER IDENTITY(1,1) NOT NULL, USERPRNUM VARCHAR(50) NOT NULL, USERPRPASSWD VARCHAR(20), USERPRMNAME VARCHAR(40), USERPRSNAME VARCHAR(40), USERPRFNAME VARCHAR(40), USERPRLNAME VARCHAR(40), USERPRSTATUSID INTEGER, USERPRADDR1 VARCHAR(60),USERPRADDR2 VARCHAR(60),USERPRCITY VARCHAR(30),USERPRSTATE VARCHAR(2),USERPRZIP VARCHAR(12),USERPRCOUNTRY VARCHAR(50),USERPREMAIL VARCHAR(50), USERPRPHONE VARCHAR(50), USERPREMPTITLEID INTEGER, USERPRLASTLOGIN TIMESTAMP, USERPRACCESSLEVEL INTEGER, USERPRACCESSMOD INTEGER, USERPRINACTDATE DATETIME, USERPRHIREDATE DATETIME, USERPRTERMDATE DATETIME, USERPRIPRESTRICTOVERRIDE char(1), USERDATA VARCHAR(80), USERPRSECONDLOGINOVERRIDE char(1) default 'F', CONSTRAINT USERPROFILEPK1 PRIMARY KEY (COMPANYID, USERPRID))
+CREATE TABLE USERPROFILE (COMPANYID INTEGER NOT NULL, USERPRID INTEGER IDENTITY(1,1) NOT NULL, USERPRNUM VARCHAR(50) NOT NULL, USERPRPASSWD VARCHAR(20), USERPRMNAME VARCHAR(40), USERPRSNAME VARCHAR(40), USERPRFNAME VARCHAR(40), USERPRLNAME VARCHAR(40), USERPRSTATUSID INTEGER, USERPRADDR1 VARCHAR(60),USERPRADDR2 VARCHAR(60),USERPRCITY VARCHAR(30),USERPRSTATE VARCHAR(2),USERPRZIP VARCHAR(12),USERPRCOUNTRY VARCHAR(50),USERPREMAIL VARCHAR(50), USERPRPHONE VARCHAR(50), USERPREMPTITLEID INTEGER, USERPRLASTLOGIN TIMESTAMP, USERPRACCESSLEVEL INTEGER, USERPRACCESSMOD INTEGER, USERPRINACTDATE DATETIME, USERPRHIREDATE DATETIME, USERPRTERMDATE DATETIME, USERPRIPRESTRICTOVERRIDE char(1), USERDATA VARCHAR(80), USERPRSECONDLOGINOVERRIDE char(1) DEFAULT 'F', USERPMGRRECUREMAILSOVERRIDE char(1) DEFAULT 'F', CONSTRAINT USERPROFILEPK1 PRIMARY KEY (COMPANYID, USERPRID))
 CREATE TABLE ANNOUNCEMENT (COMPANYID INTEGER NOT NULL, ANNOUNCID INTEGER IDENTITY(1,1) NOT NULL, ANNOUNCTITLE VARCHAR(100), ANNOUNCMESSAGE VARCHAR(255), ANNOUNCEXP DATETIME, ANNOUNCURL VARCHAR(255), ANNOUNCPOSTDATE DATETIME, USERDATA VARCHAR(80), CONSTRAINT ANNOUNCEMENTPK1 PRIMARY KEY (COMPANYID, ANNOUNCID))
 CREATE TABLE RESOURCE (COMPANYID INTEGER NOT NULL, RESOURCID INTEGER IDENTITY(1,1) NOT NULL, RESOURCTITLE VARCHAR(100), RESOURCMESSAGE VARCHAR(255), RESOURCEXP DATETIME, RESOURCURL VARCHAR(255), RESOURCPOSTDATE DATETIME, RESOURCTYPE INTEGER, USERDATA VARCHAR(80), CONSTRAINT RESOURCEPK1 PRIMARY KEY (COMPANYID, RESOURCID))
 CREATE TABLE USERGROUP (COMPANYID INTEGER NOT NULL, USERPRID INTEGER NOT NULL, ILSGROUPID INTEGER NOT NULL, CONSTRAINT USERGROUPPK1 PRIMARY KEY (COMPANYID, USERPRID, ILSGROUPID))
@@ -18,9 +18,6 @@
 CREATE TABLE GROUPTYPE (COMPANYID INTEGER NOT NULL, GROUPTYPEID INTEGER NOT NULL, GROUPTYPENAME VARCHAR(40), GROUPTYPEDESC VARCHAR(80), CONSTRAINT GROUPTYPEPK1 PRIMARY KEY (COMPANYID, GROUPTYPEID))
 CREATE TABLE COURSETYPE (COMPANYID INTEGER NOT NULL, COURSETYPEID INTEGER NOT NULL, COURSETYPENAME VARCHAR(40), COURSETYPEDESC VARCHAR(80), CONSTRAINT COURSETYPEPK1 PRIMARY KEY (COMPANYID, COURSETYPEID))
 CREATE TABLE SECURITYMODE (COMPANYID INTEGER NOT NULL, SECMODDESC VARCHAR(75) NOT NULL, SECMODVAL INTEGER NOT NULL, CONSTRAINT SECURITYMODEPK1 PRIMARY KEY (COMPANYID, SECMODDESC))
-CREATE VIEW USERCOURSEASSIGNMENTS WITH SCHEMABINDING AS SELECT DISTINCT T2.COMPANYID, T2.USERPRID, COALESCE (T9.COURSID, T1.COURSID) AS COURSID FROM   dbo.USERGROUP AS T2 INNER JOIN dbo.COURSEGROUP AS T3 ON T3.COMPANYID = T2.COMPANYID AND T3.ILSGROUPID = T2.ILSGROUPID INNER JOIN dbo.COURSE AS T1 ON T1.COMPANYID = T3.COMPANYID AND T1.COURSID = T3.COURSID LEFT OUTER JOIN dbo.CURRICULUMCOURSE AS T5 ON T5.COMPANYID = T1.COMPANYID AND T5.CURRICULUMID = T1.COURSID AND T1.COURSISCURRICULUM = 'T' LEFT OUTER JOIN dbo.COURSE AS T9 ON T5.COMPANYID IS NOT NULL AND T9.COMPANYID = T5.COMPANYID AND T9.COURSID = T5.COURSID WHERE (T9.COURSID IS NULL) AND (T1.COURSISCURRICULUM IS NULL) AND (T9.COURSID IS NULL) AND (T1.COURSISQUICKVIEW IS NULL OR T1.COURSISQUICKVIEW <> 'T') OR (T9.COURSID IS NULL) AND (T1.COURSISCURRICULUM IS NULL) AND (T9.COURSID IS NOT NULL) AND (T9.COURSISQUICKVIEW IS NULL OR T9.COURSISQUICKVIEW <> 'T') OR (T9.COURSID IS NULL) AND (T1.COURSISCURRICULUM <> 'T') AND (T1.COURSISQUICKVIEW IS NULL OR T1.COURSISQUICKVIEW <> 'T') OR (T9.COURSID IS NOT NULL) AND (T1.COURSISCURRICULUM <> 'T') AND (T9.COURSISQUICKVIEW IS NULL OR T9.COURSISQUICKVIEW <> 'T') OR (T9.COURSID IS NULL) AND (T1.COURSISQUICKVIEW IS NULL OR T1.COURSISQUICKVIEW <> 'T') AND (T1.COURSID <> T9.COURSID) OR (T9.COURSID IS NOT NULL) AND (T9.COURSISQUICKVIEW IS NULL OR T9.COURSISQUICKVIEW <> 'T') AND (T1.COURSID <> T9.COURSID);
-CREATE VIEW COURSEATTEMPTSTATUS WITH SCHEMABINDING AS SELECT CA.COMPANYID, CA.USERPRID, CA.COURSID, CA.COURSATTID, CA.CACOMPLETEDATE, CA.CAEXPIREDON,  COALESCE(CA.CASTATUSID, 0) AS CASTATUSID, CASE COALESCE(CA.CASTATUSID, 0) WHEN 3 THEN 1 WHEN 0 THEN 1 ELSE 0 END AS CRS_OPEN, CASE COALESCE(CA.CASTATUSID, 0) WHEN 1 THEN 1 ELSE 0 END               AS CRS_COMPLETED, CASE COALESCE(CA.CASTATUSID, 0) WHEN 2 THEN 1 ELSE 0 END               AS CRS_FAILED FROM DBO.COURSEATTEMPT CA;
-CREATE NONCLUSTERED INDEX CAEXPIREDONINDEX ON COURSEATTEMPT (COMPANYID,CAEXPIREDON) INCLUDE (USERPRID,COURSID,CACOMPLETEDATE,CASTATUSID)
 INSERT INTO COMPANY (CONAME, COFUNDSAVAIL, COPERSEATCOST, COLOGOURL, COCOPYRIGHT) VALUES ('ILS', 0.00, 0.00, 'images/logo.gif', 'Copyright (C) 2006 ILS')
 INSERT INTO SYSCONF (COMPANYID, SYSCFCOLLABURL, SYSCFEMAILSRV) VALUES (1, 'http://crosswire.org/forums', 'mail.crosswire.org')
 INSERT INTO COURSEATTSTATUS (COMPANYID, CASTATUSID, CASTATUSDESC) VALUES (1, 0, 'NEW')
@@ -35,3 +32,15 @@
 INSERT INTO SECURITYMODE (COMPANYID, SECMODDESC, SECMODVAL) VALUES (1, 'Default Manager', 8)
 INSERT INTO SECURITYMODE (COMPANYID, SECMODDESC, SECMODVAL) VALUES (1, 'Badging Officer', 520)
 INSERT INTO SECURITYMODE (COMPANYID, SECMODDESC, SECMODVAL) VALUES (1, 'Course Developer', 9)
+
+
+
+-- run separately
+
+CREATE VIEW USERCOURSEASSIGNMENTS WITH SCHEMABINDING AS SELECT DISTINCT T2.COMPANYID, T2.USERPRID, COALESCE (T9.COURSID, T1.COURSID) AS COURSID FROM   dbo.USERGROUP AS T2 INNER JOIN dbo.COURSEGROUP AS T3 ON T3.COMPANYID = T2.COMPANYID AND T3.ILSGROUPID = T2.ILSGROUPID INNER JOIN dbo.COURSE AS T1 ON T1.COMPANYID = T3.COMPANYID AND T1.COURSID = T3.COURSID LEFT OUTER JOIN dbo.CURRICULUMCOURSE AS T5 ON T5.COMPANYID = T1.COMPANYID AND T5.CURRICULUMID = T1.COURSID AND T1.COURSISCURRICULUM = 'T' LEFT OUTER JOIN dbo.COURSE AS T9 ON T5.COMPANYID IS NOT NULL AND T9.COMPANYID = T5.COMPANYID AND T9.COURSID = T5.COURSID WHERE (T9.COURSID IS NULL) AND (T1.COURSISCURRICULUM IS NULL) AND (T9.COURSID IS NULL) AND (T1.COURSISQUICKVIEW IS NULL OR T1.COURSISQUICKVIEW <> 'T') OR (T9.COURSID IS NULL) AND (T1.COURSISCURRICULUM IS NULL) AND (T9.COURSID IS NOT NULL) AND (T9.COURSISQUICKVIEW IS NULL OR T9.COURSISQUICKVIEW <> 'T') OR (T9.COURSID IS NULL) AND (T1.COURSISCURRICULUM <> 'T') AND (T1.COURSISQUICKVIEW IS NULL OR T1.COURSISQUICKVIEW <> 'T') OR (T9.COURSID IS NOT NULL) AND (T1.COURSISCURRICULUM <> 'T') AND (T9.COURSISQUICKVIEW IS NULL OR T9.COURSISQUICKVIEW <> 'T') OR (T9.COURSID IS NULL) AND (T1.COURSISQUICKVIEW IS NULL OR T1.COURSISQUICKVIEW <> 'T') AND (T1.COURSID <> T9.COURSID) OR (T9.COURSID IS NOT NULL) AND (T9.COURSISQUICKVIEW IS NULL OR T9.COURSISQUICKVIEW <> 'T') AND (T1.COURSID <> T9.COURSID);
+
+
+CREATE VIEW COURSEATTEMPTSTATUS WITH SCHEMABINDING AS SELECT CA.COMPANYID, CA.USERPRID, CA.COURSID, CA.COURSATTID, CA.CACOMPLETEDATE, CA.CAEXPIREDON,  COALESCE(CA.CASTATUSID, 0) AS CASTATUSID, CASE COALESCE(CA.CASTATUSID, 0) WHEN 3 THEN 1 WHEN 0 THEN 1 ELSE 0 END AS CRS_OPEN, CASE COALESCE(CA.CASTATUSID, 0) WHEN 1 THEN 1 ELSE 0 END               AS CRS_COMPLETED, CASE COALESCE(CA.CASTATUSID, 0) WHEN 2 THEN 1 ELSE 0 END               AS CRS_FAILED FROM DBO.COURSEATTEMPT CA;
+
+
+CREATE NONCLUSTERED INDEX CAEXPIREDONINDEX ON COURSEATTEMPT (COMPANYID,CAEXPIREDON) INCLUDE (USERPRID,COURSID,CACOMPLETEDATE,CASTATUSID);

Copied: branches/1.6/db/mssql/upgrade1.80.5-1.sql (from rev 1409, trunk/db/mssql/upgrade1.80.5-1.sql)
===================================================================
--- branches/1.6/db/mssql/upgrade1.80.5-1.sql	                        (rev 0)
+++ branches/1.6/db/mssql/upgrade1.80.5-1.sql	2016-03-10 18:44:41 UTC (rev 1410)
@@ -0,0 +1 @@
+alter table USERPROFILE add USERPMGRRECUREMAILSOVERRIDE char(1) DEFAULT 'F';

Copied: branches/1.6/db/mssql/upgrade185.1.sql (from rev 1373, trunk/db/mssql/upgrade185.1.sql)
===================================================================
--- branches/1.6/db/mssql/upgrade185.1.sql	                        (rev 0)
+++ branches/1.6/db/mssql/upgrade185.1.sql	2016-03-10 18:44:41 UTC (rev 1410)
@@ -0,0 +1 @@
+alter table USERPROFILE add USERPMGRRECUREMAILSOVERRIDE char(1) DEFAULT 'F';

Modified: branches/1.6/src/com/resolutions/ils/data/Group.java
===================================================================
--- branches/1.6/src/com/resolutions/ils/data/Group.java	2016-03-10 18:38:22 UTC (rev 1409)
+++ branches/1.6/src/com/resolutions/ils/data/Group.java	2016-03-10 18:44:41 UTC (rev 1410)
@@ -97,8 +97,11 @@
 	}
 
     static public Vector getUserGroups(ILSSession session, int groupTypeID, int userID) {
+	return getUserGroups(session.getCompanyID(), groupTypeID, userID);
+    }
+    static public Vector getUserGroups(int companyID, int groupTypeID, int userID) {
         Group query = new Group();
-        query.setValue("COMPANYID", new Integer(session.getCompanyID()));
+        query.setValue("COMPANYID", new Integer(companyID));
         query.setValue("USERPRID", new Integer(userID));
         query.setGroupTypeID(groupTypeID);
         return query.getDataSet(LOOKUPUSERGROUPS);

Modified: branches/1.6/src/com/resolutions/ils/data/UserProfile.java
===================================================================
--- branches/1.6/src/com/resolutions/ils/data/UserProfile.java	2016-03-10 18:38:22 UTC (rev 1409)
+++ branches/1.6/src/com/resolutions/ils/data/UserProfile.java	2016-03-10 18:44:41 UTC (rev 1410)
@@ -8,6 +8,9 @@
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.text.SimpleDateFormat;
 
 import javax.mail.Message;
 import javax.mail.MessagingException;
@@ -16,6 +19,7 @@
 import javax.mail.internet.InternetAddress;
 import javax.mail.internet.MimeMessage;
 import javax.servlet.http.HttpSession;
+import javax.servlet.ServletContext;
 
 import org.apache.log4j.Logger;
 import org.crosswire.data.DataObject;
@@ -25,6 +29,7 @@
 import com.resolutions.ils.ILSSession;
 import com.resolutions.ils.Utils;
 import java.util.Hashtable;
+import java.io.StringWriter;
 
 public class UserProfile extends DataObject {
 	
@@ -75,7 +80,13 @@
 	static String COUNTWOULDBEDELETES = "SELECT COUNT(*) WOULDBE FROM ("+SELECTOLDIDS+") TMPTABLE";
 	static String LOOKUPUSERGROUPS = "SELECT * FROM ILSGROUP T1, USERGROUP T2 WHERE T1.ILSGROUPID=T2.ILSGROUPID AND T2.USERPRID={USERPRID} AND T1.COMPANYID={COMPANYID} AND T2.COMPANYID={COMPANYID}";
 
+	static String RECURRENT_TRAINING_REPORT = "SELECT DISTINCT CASS.COMPANYID, CASS.USERPRID, CASS.COURSID, UP.USERPRLNAME, UP.USERPRFNAME, UP.USERPRNUM, "
+		+ " (SELECT MAX(GROUPNAME) FROM USERGROUP UG JOIN ILSGROUP IG ON UG.ILSGROUPID=IG.ILSGROUPID AND UG.USERPRID=UP.USERPRID AND GROUPTYPEID=2) WORKGROUP," 
+		+ " (SELECT MAX(GROUPNAME) FROM USERGROUP UG JOIN ILSGROUP IG ON UG.ILSGROUPID=IG.ILSGROUPID AND UG.USERPRID=UP.USERPRID AND GROUPTYPEID=1) ROLE, "
+		+ "C.COURSNAME, CA.CACOMPLETEDATE, CASE C.COURSPASSEXPDAYS WHEN 0 THEN CA.CAEXPIREDON ELSE COALESCE(CA.CAEXPIREDON, CA.CACOMPLETEDATE+C.COURSPASSEXPDAYS) END AS CAEXPIREDON, DATEDIFF(day, CA.CAEXPIREDON, CURRENT_TIMESTAMP) as DAYSEXPIRED, CASE C.COURSPASSEXPDAYS WHEN 0 THEN NULL ELSE C.COURSPASSEXPDAYS - DATEDIFF(day, CA.CACOMPLETEDATE, CURRENT_TIMESTAMP) END as DAYSSHOULDEXPIRE from USERCOURSEASSIGNMENTSWITHGROUPS CASS LEFT JOIN COURSE C ON C.COURSID = CASS.COURSID LEFT JOIN COURSEATTEMPT CA ON CA.USERPRID=CASS.USERPRID AND CA.COURSID=CASS.COURSID INNER JOIN (SELECT USERPRID, COURSID, MAX(CACOMPLETEDATE) as max_date FROM COURSEATTEMPT GROUP BY USERPRID, COURSID)a on a.USERPRID = CA.USERPRID AND a.COURSID=CA.COURSID and a.max_date = CA.CACOMPLETEDATE LEFT JOIN USERPROFILE UP ON UP.COMPANYID=CASS.COMPANYID AND UP.USERPRID = CASS.USERPRID WHERE CASS.COMPANYID={COMPANYID} AND (DATEDIFF(day, CA.CAEXPIREDON, CURRENT_TIMESTAMP) >= 0 OR CASE C.COURSPASSEXPDAYS WHEN 0 THEN NULL ELSE C.COURSPASSEXPDAYS - DATEDIFF(day, CA.CACOMPLETEDATE, CURRENT_TIMESTAMP) END <={DAYSTILEXP}) AND UP.USERPRSTATUSID=" + STATUS_ACTIVE;
+static String RECURRENT_TRAINING_REPORT_LIMIT_TO_MANAGER = " AND CASS.USERPRID IN (SELECT DISTINCT UG.USERPRID FROM MANAGERGROUP MG LEFT JOIN USERGROUP UG ON UG.COMPANYID = MG.COMPANYID AND UG.ILSGROUPID=MG.ILSGROUPID WHERE MG.COMPANYID={COMPANYID} AND MG.USERPRID={USERPRID}) AND (GROUPTYPEID <> 2 OR ILSGROUPID IN (SELECT ILSGROUPID FROM MANAGERGROUP WHERE COMPANYID={COMPANYID} AND USERPRID={USERPRID}))";
 
+
     private boolean isRoleLoaded              = false;
     private boolean isWorkgroupLoaded         = false;
     private boolean isCourseSummaryDataLoaded = false;
@@ -401,6 +412,28 @@
         return results;
     }
 
+	static public Vector<UserProfile> getManagers(ILSSession session) {
+		return getManagers(session, false);
+	}
+	static public Vector<UserProfile> getManagers(ILSSession session, boolean excludeRecurEmailOverrides) {
+		return getManagers(session.getCompanyID(), excludeRecurEmailOverrides);
+	}
+	static public Vector<UserProfile> getManagers(int companyID, boolean excludeRecurEmailOverrides) {
+
+		UserProfile retVal = new UserProfile();
+
+		String sql = "SELECT * FROM USERPROFILE UP WHERE UP.COMPANYID={COMPANYID} AND EXISTS (SELECT USERPRID FROM MANAGERGROUP MG WHERE MG.USERPRID=UP.USERPRID AND MG.COMPANYID={COMPANYID})";
+		retVal.setCompanyID(companyID);
+
+		if (excludeRecurEmailOverrides) {
+			sql += " AND UP.USERPMGRRECUREMAILSOVERRIDE<>'T'";
+		}
+
+		Vector<UserProfile> results = retVal.getDataSet(sql);
+
+		return results;
+	}
+
     
     static String USERGROUPCOURSESUMMARY=
     		"SELECT GRP.ILSGROUPID, GRP.GROUPNAME, " +
@@ -497,6 +530,33 @@
         return retVal.getDataSet(sql + " OPTION (RECOMPILE)");
     }
 
+	public Vector<UserProfile> getManagerRecurrentTrainingReport(int daysTilExpire) {
+		int limitToManager = (getUserProfileAccessLevel() <= UserProfile.ACCESS_MANAGER) ? getUserProfileID() : -1;
+		return UserProfile.getManagerRecurrentTrainingReport(this.getCompanyID(), daysTilExpire, limitToManager);
+	}
+	static public Vector<UserProfile> getManagerRecurrentTrainingReport(ILSSession session, int daysTilExpire) {
+		return getManagerRecurrentTrainingReport(session, daysTilExpire, -1);
+	}
+	static public Vector<UserProfile> getManagerRecurrentTrainingReport(ILSSession session, int daysTilExpire, int limitToManager) {
+		return getManagerRecurrentTrainingReport(session.getCompanyID(), daysTilExpire, limitToManager);
+	}
+	static public Vector<UserProfile> getManagerRecurrentTrainingReport(int companyID, int daysTilExpire, int limitToManagerID) {
+		UserProfile retVal = new UserProfile();
+		String sql = RECURRENT_TRAINING_REPORT;
+		retVal.setCompanyID(companyID);
+		retVal.setIntValue("DAYSTILEXP", daysTilExpire);
+		if (limitToManagerID != -1) {
+			sql += RECURRENT_TRAINING_REPORT_LIMIT_TO_MANAGER;
+			retVal.setUserProfileID(limitToManagerID);
+		}
+		Vector<UserProfile> results = retVal.getDataSet(sql + " OPTION (RECOMPILE)");
+		for (UserProfile up: results) {
+			up.isRoleLoaded = true;
+			up.isWorkgroupLoaded = true;
+		}
+		return results;
+	}
+
     public UserProfile []getManagers() {
         String sql = LOOKUP + " AND USERPRID IN (" + LOOKUPMANAGERS + ")";
         Vector<UserProfile> rows = this.getDataSet(sql);
@@ -683,6 +743,14 @@
         return ("T".equals(getValue("USERPRIPRESTRICTOVERRIDE")));
     }
 
+    public void setMgrRecurEmailOverride(boolean val) {
+        setValue("USERPMGRRECUREMAILSOVERRIDE", (val) ? "T" : "F");
+    }
+
+    public boolean isMgrRecurEmailOverride() {
+        return ("T".equals(getValue("USERPMGRRECUREMAILSOVERRIDE")));
+    }
+
     public void setSecondaryValidationOverride(boolean val) {
         setValue("USERPRSECONDLOGINOVERRIDE", (val) ? "T" : "F");
     }
@@ -739,7 +807,10 @@
 		return getStringValue("ROLE");
 	}
 	public String getRoles(ILSSession session) {
-		Vector tmpg = Group.getUserGroups(session, Group.GROUPTYPE_ROLE, getUserProfileID());
+		return getRoles();
+	}
+	public String getRoles() {
+		Vector tmpg = Group.getUserGroups(getCompanyID(), Group.GROUPTYPE_ROLE, getUserProfileID());
 		String upRole = "";
 		if (tmpg != null) {
 			for (Object g : tmpg) {
@@ -759,7 +830,10 @@
 		return getStringValue("WORKGROUP");
 	}
 	public String getWorkgroups(ILSSession session) {
-		Vector tmpg = Group.getUserGroups(session, Group.GROUPTYPE_LOCATION, getUserProfileID());
+		return getWorkgroups();
+	}
+	public String getWorkgroups() {
+		Vector tmpg = Group.getUserGroups(getCompanyID(), Group.GROUPTYPE_LOCATION, getUserProfileID());
 		String upLocation = "";
 		if (tmpg != null) {
 			for (Object g : tmpg) {
@@ -889,6 +963,100 @@
         return results.size();
     }
 
+	public synchronized void emailMgrRecurReport(ServletContext context, int daysTilDue) {
+		StringWriter out = new StringWriter();
+		SimpleDateFormat df  = new SimpleDateFormat("MM/dd/yyyy");
+		Properties sysConfig = Utils.getSysConfig(context, getCompanyID());
+		String subjectTemplate = sysConfig.getProperty("EmailTemplate7Subject");
+		String bodyTemplate    = sysConfig.getProperty("EmailTemplate7Body");
+		String from            = sysConfig.getProperty("SendMailFrom");
+		Vector<UserProfile> userProfiles = getManagerRecurrentTrainingReport(daysTilDue);
+		int expiredCount = 0;
+		for (UserProfile up : userProfiles) {
+			if (up.getValue("DAYSEXPIRED") != null) ++expiredCount;
+		}
+		Collections.sort(userProfiles, new Comparator() {
+			public int compare(Object o1, Object o2) {
+				UserProfile p1 = (UserProfile)o1;
+				UserProfile p2 = (UserProfile)o2;
+				return p2.getIntValue("DAYSEXPIRED") - p1.getIntValue("DAYSEXPIRED");
+			}
+		});
+
+		String companyName = Company.getCompany(getCompanyID()).getCompanyName();
+		out.write(companyName + "\n");
+		out.write(getUserProfileFirstName() + " " + getUserProfileLastName() + "\n");
+		out.write("Report Run " + df.format(new Date()) + "\n\n");
+		out.write("Recurrent Training Management Report\n\n");
+		out.write("Past Due Training\n\n");
+		out.write("Last Name,");
+		out.write("First Name,");
+		out.write("Emp ID,");
+//TODO: translate these
+		out.write("Workgroup,");
+		out.write("Role,");
+		out.write("Course Name,Date Due,Days Past Due\n");
+		for (UserProfile up : userProfiles) {
+			if (up.getValue("DAYSEXPIRED") == null) continue;
+			Date lastDate = up.getDateValue("CAEXPIREDON");
+			String eDate = (lastDate != null) ? df.format(lastDate) : "";
+			out.write("\""+up.getUserProfileLastName().replaceAll("\"", "\"\"") + "\",");
+			out.write("\""+up.getUserProfileFirstName().replaceAll("\"", "\"\"") + "\",");
+			out.write("\""+up.getUserProfileNum().replaceAll("\"", "\"\"") + "\",");
+			out.write("\""+up.getWorkgroups().replaceAll("\"", "\"\"") + "\",");
+			out.write("\""+up.getRoles().replaceAll("\"", "\"\"") + "\",");
+			out.write(up.getStringValue("COURSNAME") + ",");
+			out.write(eDate + ",");
+			out.write(up.getIntValue("DAYSEXPIRED") + ",");
+			out.write("\n");
+		}
+		out.write("\n\nTraining Required Next " + daysTilDue+" Days\n\n");
+		out.write("Last Name,");
+		out.write("First Name,");
+		out.write("Emp ID,");
+		out.write("Workgroup,");
+		out.write("Role,");
+		out.write("Course Name,Date Due,Days to Due Date\n");
+		Collections.sort(userProfiles, new Comparator() {
+			public int compare(Object o1, Object o2) {
+				UserProfile p1 = (UserProfile)o1;
+				UserProfile p2 = (UserProfile)o2;
+				return p1.getIntValue("DAYSSHOULDEXPIRE") - p2.getIntValue("DAYSSHOULDEXPIRE");
+			}
+		});
+
+		for (UserProfile up : userProfiles) {
+			if (up.getValue("DAYSEXPIRED") != null) continue;
+			Date lastDate = up.getDateValue("CAEXPIREDON");
+			String eDate = (lastDate != null) ? df.format(lastDate) : "";
+			out.write("\""+up.getUserProfileLastName().replaceAll("\"", "\"\"") + "\",");
+			out.write("\""+up.getUserProfileFirstName().replaceAll("\"", "\"\"") + "\",");
+			out.write("\""+up.getUserProfileNum().replaceAll("\"", "\"\"") + "\",");
+			out.write("\""+up.getWorkgroups().replaceAll("\"", "\"\"") + "\",");
+			out.write("\""+up.getRoles().replaceAll("\"", "\"\"") + "\",");
+			out.write(up.getStringValue("COURSNAME") + ",");
+			out.write(eDate + ",");
+			out.write(up.getIntValue("DAYSSHOULDEXPIRE") + ",");
+			out.write("\n");
+		}
+		try {
+			String to = getUserProfileEMail();
+			java.util.Hashtable params = new java.util.Hashtable();
+			params.put("CONAME", companyName);
+			params.put("SITEURL", sysConfig.getProperty("SiteURL", "your training site"));
+			params.putAll(this.getData());
+			String subject = Utils.replaceParams(subjectTemplate, params);
+			String body    = Utils.replaceParams(bodyTemplate, params);
+			body += sysConfig.getProperty("SendMailSig", "");
+logger.info("sending email to: " + to + "; body: " + body);
+			SMTPMail.sendEmail(sysConfig, from, to, subject, body, "recurrentReport.csv", out.toString(), "text/csv", true);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+		Utils.closeMailConnection();
+	}
+
 	public String toXML() {
 		return toXML(DETAIL_COMPLETE);
 	}

Copied: branches/1.6/src/com/resolutions/jobs/MgrRecurEMails.java (from rev 1373, trunk/src/com/resolutions/jobs/MgrRecurEMails.java)
===================================================================
--- branches/1.6/src/com/resolutions/jobs/MgrRecurEMails.java	                        (rev 0)
+++ branches/1.6/src/com/resolutions/jobs/MgrRecurEMails.java	2016-03-10 18:44:41 UTC (rev 1410)
@@ -0,0 +1,93 @@
+package com.resolutions.jobs;
+
+import java.util.Properties;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import javax.servlet.ServletContext;
+
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+import org.apache.log4j.Logger;
+
+import com.resolutions.ils.Utils;
+import com.resolutions.ils.data.Company;
+import com.resolutions.ils.data.UserProfile;
+
+public class MgrRecurEMails implements Job {
+
+	static SimpleDateFormat df = new SimpleDateFormat();
+	static Logger logger = Logger.getLogger(MgrRecurEMails.class);
+
+	public void execute (JobExecutionContext context) throws JobExecutionException {
+		logger.info("Running Batch Job MgrRecurEmail");
+		ServletContext servletContext = StartupScheduler.servletConfig.getServletContext();
+		for (Object o : Company.getAllCompanies()) {
+			Company c = (Company)o;
+			Properties sysConfig = Utils.getSysConfig(servletContext, c.getCompanyID());
+			boolean enableRecurEmails = "on".equals(sysConfig.getProperty("EmailEnableManagerRecurReport", ""));
+			int recurReportNumDays = 30; try { recurReportNumDays = Integer.parseInt(sysConfig.getProperty("RecurReportNumDays")); } catch (Exception e) {}
+			int recurReportDayOfMonth = 1; try { recurReportDayOfMonth = Integer.parseInt(sysConfig.getProperty("RecurReportDayOfMonth")); } catch (Exception e) {}
+			int recurReportDay = Calendar.SUNDAY; try { recurReportDay = Integer.parseInt(sysConfig.getProperty("RecurReportDay")); } catch (Exception e) {}
+			String recurReportFreq = sysConfig.getProperty("RecurReportFreq");
+			if (enableRecurEmails) {
+                                Properties lastJobs = new Properties();
+                                File propName = new File(servletContext.getRealPath("/WEB-INF/lastjobs."+c.getCompanyID() + ".properties"));
+                                if (propName.exists()) {
+					try {
+						FileInputStream propFile = new FileInputStream(propName);
+						lastJobs.load(propFile);
+						propFile.close();
+					}
+					catch (Exception e) {}
+                                }
+				Calendar cal = GregorianCalendar.getInstance();
+				cal.set(2000, 1, 1);
+				Date lastDate = cal.getTime(); try { lastDate = df.parse(lastJobs.getProperty("ManagerRecurReportEmails")); } catch (Exception e) {}
+				cal.setTime(lastDate);
+
+				if ("MONTHLY".equals(recurReportFreq)) {
+					// Add 1 month and a day to last report run, then back up until we hit our target date
+					cal.add(Calendar.MONTH, 1);
+					if (cal.get(Calendar.DAY_OF_MONTH) < recurReportDayOfMonth) cal.add(Calendar.MONTH, -1);
+					cal.set(Calendar.DAY_OF_MONTH, recurReportDayOfMonth);
+				}
+				else if ("WEEKLY".equals(recurReportFreq)) {
+					cal.add(Calendar.DAY_OF_MONTH, 7);
+					if (cal.get(Calendar.DAY_OF_WEEK) < recurReportDay) cal.add(Calendar.DAY_OF_MONTH, -1*cal.get(Calendar.DAY_OF_WEEK));
+					int adjust = cal.get(Calendar.DAY_OF_WEEK)-recurReportDay;
+					if (adjust > 0) cal.add(Calendar.DAY_OF_MONTH, adjust*-1);
+				}
+				else {
+					cal.add(Calendar.DAY_OF_MONTH, 1);
+				}
+				cal.add(Calendar.HOUR, -4);	// be sure we don't miss out date by just a few hours. report shouldn't take more than this long to run the reports.
+				lastDate = cal.getTime();
+				if (new Date().after(lastDate)) {
+
+					for (UserProfile up : UserProfile.getManagers(c.getCompanyID(), true)) {
+						up.emailMgrRecurReport(servletContext, recurReportNumDays);
+					}
+
+					lastJobs.setProperty("ManagerRecurReportEmails", df.format(new Date()));
+					try {
+						FileOutputStream propFile = new FileOutputStream(propName);
+						lastJobs.store(propFile, "last saved from MgrRecurEmail batch job");
+						propFile.close();
+					}
+					catch (Exception e) {}
+				}
+			}
+		}
+		logger.info("Finished Batch Job MgrRecurEmail");
+	}
+
+}
+

Modified: branches/1.6/webapp/WEB-INF/classes/jobs.xml
===================================================================
--- branches/1.6/webapp/WEB-INF/classes/jobs.xml	2016-03-10 18:38:22 UTC (rev 1409)
+++ branches/1.6/webapp/WEB-INF/classes/jobs.xml	2016-03-10 18:44:41 UTC (rev 1410)
@@ -18,19 +18,22 @@
     
     <schedule>
 	    <job>
+			<name>MgrRecurEMails</name>
+			<group>MgrRecEMails</group>
+			<description>Manager Recurrent Training EMails</description>
+			<job-class>com.resolutions.jobs.MgrRecurEMails</job-class>
+			<volatility>true</volatility>
+			<durability>false</durability>
+			<recover>true</recover>
+	    </job>
+	    <job>
 			<name>WarnCourseExpEMails</name>
 			<group>WarnEMails</group>
 			<description>Daily Warnings EMails</description>
 			<job-class>com.resolutions.jobs.WarnCourseExpEMails</job-class>
-	        <volatility>true</volatility>
-	        <durability>false</durability>
-	        <recover>true</recover>
-	        <job-data-map>
-	            <entry>
-	                <key>someOtherKey</key>
-	                <value>someOtherValue</value>
-	            </entry>
-	        </job-data-map>
+			<volatility>true</volatility>
+			<durability>false</durability>
+			<recover>true</recover>
 	    </job>
 	    <job>
 			<name>CleanAPISessionTokens</name>
@@ -82,6 +85,15 @@
 		    <cron-expression>0 0 0 * * ?</cron-expression>
 	        </cron>
         </trigger>
+	    <trigger>
+	        <cron>
+		    <name>MgrRecurEMails</name>
+	            <group>ILSTriggers</group>
+				<job-name>MgrRecurEMails</job-name>
+				<job-group>MgrRecEMails</job-group>
+		    <cron-expression>0 0 0 * * ?</cron-expression>
+	        </cron>
+        </trigger>
 <!--
 	    <trigger>
 	        <cron>

Modified: branches/1.6/webapp/WEB-INF/lib/crosswire-integration.jar
===================================================================
(Binary files differ)

Modified: branches/1.6/webapp/WEB-INF/lib/ils.jar
===================================================================
(Binary files differ)

Modified: branches/1.6/webapp/admin_groupmanagement.jsp
===================================================================
--- branches/1.6/webapp/admin_groupmanagement.jsp	2016-03-10 18:38:22 UTC (rev 1409)
+++ branches/1.6/webapp/admin_groupmanagement.jsp	2016-03-10 18:44:41 UTC (rev 1410)
@@ -47,7 +47,7 @@
         }
     }
 
-    Vector groups        = Group.getAllGroups(ilsSession, Group.GROUPTYPE_LOCATION);
+    Vector<Group> groups        = (Vector<Group>) Group.getAllGroups(ilsSession, Group.GROUPTYPE_LOCATION);
 
     final String sort = request.getParameter("sort");
 
@@ -146,11 +146,11 @@
                                           <th><a href="admin_groupmanagement.jsp?sort=desc">Description</a></th>
                                       </tr>
 <%
-    for (int j = 0; j < groups.size(); j++) {
-        Group g = (Group)groups.get(j);
+	int groupCounter = 0;
+    for (Group g : groups) {
 %>
                                       <tr>
-                                          <td><input id="locck<%=j%>" type="checkbox" name="gid" value="<%=g.getGroupID()%>"></td>
+                                          <td><input id="locck<%=groupCounter++%>" type="checkbox" name="gid" value="<%=g.getGroupID()%>"></td>
                                           <td><%=g.getGroupName()%></td>
                                           <td><%=g.getGroupDesc()%></td>
                                       </tr>

Modified: branches/1.6/webapp/admin_profile.jsp
===================================================================
--- branches/1.6/webapp/admin_profile.jsp	2016-03-10 18:38:22 UTC (rev 1409)
+++ branches/1.6/webapp/admin_profile.jsp	2016-03-10 18:44:41 UTC (rev 1410)
@@ -198,6 +198,8 @@
         if (val != null) current.setUserProfilePhone(val);
         val = request.getParameter("ipResOver");
         current.setIPRestrictOverride("true".equals(val));
+        val = request.getParameter("mgrRecOver");
+        current.setMgrRecurEmailOverride("true".equals(val));
         val = request.getParameter("secondValidOver");
         current.setSecondaryValidationOverride("true".equals(val));
         val = request.getParameter("hdate");
@@ -575,6 +577,11 @@
     <td valign="middle" class="formHeadings">Override IP Address Restriction: </td>
     <td width="228"><input <%=(editMisc)?"":"disabled=\"true\""%> name="ipResOver" value="true" type="checkbox" <%=current.isIPRestrictOverride()?"checked=\"checked\"":""%> /></td>
   </tr>
+  
+  <tr>
+    <td valign="middle" class="formHeadings">Override (Disable) Manager Recurrent Report Emails: </td>
+    <td width="228"><input <%=(editMisc)?"":"disabled=\"true\""%> name="mgrRecOver" value="true" type="checkbox" <%=current.isMgrRecurEmailOverride()?"checked=\"checked\"":""%> /></td>
+  </tr>
 
   <tr>
     <td valign="middle" class="formHeadings"><t:t>Role</t:t>: </td>
@@ -876,7 +883,7 @@
 %>
                 <tr>
                   <td><input id="pv<%=UserProfile.ACCESS_MODE_MENU_STUDENT_RECORDS %>" type="checkbox" <%= ((userPrivs & UserProfile.ACCESS_MODE_MENU_STUDENT_RECORDS) == UserProfile.ACCESS_MODE_MENU_STUDENT_RECORDS) ? "checked=\"checked\"":"" %> name="priv" value="<%=UserProfile.ACCESS_MODE_MENU_STUDENT_RECORDS %>" /></td>
-                  <td>Student Records<br>
+                  <td>Reports<br>
                     <table width="200" border="0" cellspacing="1" cellpadding="0">
 <%
 

Modified: branches/1.6/webapp/admin_studentrecords.jsp
===================================================================
--- branches/1.6/webapp/admin_studentrecords.jsp	2016-03-10 18:38:22 UTC (rev 1409)
+++ branches/1.6/webapp/admin_studentrecords.jsp	2016-03-10 18:44:41 UTC (rev 1410)
@@ -163,7 +163,7 @@
 
     if ("csv".equals(action)) {
         noHTML = true;
-        response.setContentType("application/x-csv");
+        response.setContentType("text/csv");
         response.setHeader("Content-Disposition","attachment; filename=studentReport.csv");
     }
     if (byStudent) {

Modified: branches/1.6/webapp/admin_systemmanagement.jsp
===================================================================
--- branches/1.6/webapp/admin_systemmanagement.jsp	2016-03-10 18:38:22 UTC (rev 1409)
+++ branches/1.6/webapp/admin_systemmanagement.jsp	2016-03-10 18:44:41 UTC (rev 1410)
@@ -8,6 +8,7 @@
 <%@ page import="com.resolutions.ils.data.*" %>
 <%@ page import="java.util.Vector" %>
 <%@ page import="java.util.Comparator" %>
+<%@ page import="java.util.Calendar" %>
 <%@ page import="java.util.Properties" %>
 <%@ page import="java.util.Date" %>
 <%@ page import="java.util.List" %>
@@ -104,6 +105,10 @@
 			"You can login to  your account at {SITEURL} with the credentials: \n\n" +
 			"User ID : {USERPRNUM}\n" +
 			"Password: {USERPRPASSWD}\n\n"));
+	// 7
+	emailTemplates.add(new EMailTemplate("Recurrent Training Report", "Your Employee's Past Due & Upcoming Training",
+			"The attached Recurrent Training Report includes the Past Due & Upcoming Recurrent Training for your employees at {CONAME}."
+		));
 
 	Properties sysConfigProperties = Utils.getSysConfig(session);
 	File sysConfigFile = new File(session.getServletContext().getRealPath("/WEB-INF/sysconfig."+ilsSession.getCompanyID()+".properties"));
@@ -135,7 +140,11 @@
 	String currentEmailPastDueDate2 = sysConfigProperties.getProperty("EmailPastDueDate2", "");
 	String currentEmailEnableChangePassword = sysConfigProperties.getProperty("EmailEnableChangePassword", "");
 	String currentEmailEnableStudentPassFail = sysConfigProperties.getProperty("EmailEnableStudentPassFail", "");
-	String currentEmailEnableManagerSummaryReport = sysConfigProperties.getProperty("EmailEnableManagerSummaryReport", "");
+	String currentEmailEnableManagerRecurReport = sysConfigProperties.getProperty("EmailEnableManagerRecurReport", "");
+	String currentRecurReportFreq = sysConfigProperties.getProperty("RecurReportFreq", "");
+	int currentRecurReportDay = Calendar.SUNDAY; try { currentRecurReportDay = Integer.parseInt(sysConfigProperties.getProperty("RecurReportDay", "1")); } catch (Exception e) {}
+	String currentRecurReportDayOfMonth = sysConfigProperties.getProperty("RecurReportDayOfMonth", "");
+	String currentRecurReportNumDays = sysConfigProperties.getProperty("RecurReportNumDays", "");
 	String currentEmailEnableUserEdit = sysConfigProperties.getProperty("EmailEnableUserEdit", "");
 	String currentAPIEnable = sysConfigProperties.getProperty("APIEnable", "");
 	String currentAPICallbackCourseComplete = sysConfigProperties.getProperty("APICallbackCourseComplete", "");
@@ -200,7 +209,11 @@
     String emailEnableChangePassword = request.getParameter("emailEnableChangePassword");
     String emailEnableUserEdit = request.getParameter("emailEnableUserEdit");
     String emailEnableStudentPassFail = request.getParameter("emailEnableStudentPassFail");
-    String emailEnableManagerSummaryReport = request.getParameter("emailEnableManagerSummaryReport");
+    String emailEnableManagerRecurReport = request.getParameter("emailEnableManagerRecurReport");
+    String recurReportFreq = request.getParameter("recurReportFreq");
+    String recurReportDay = recurReportDay = request.getParameter("recurReportDay");
+    String recurReportDayOfMonth = request.getParameter("recurReportDayOfMonth");
+    String recurReportNumDays = request.getParameter("recurReportNumDays");
     String emailEnableBeforeDue = request.getParameter("emailEnableBeforeDue");
     String emailEnablePastDue = request.getParameter("emailEnablePastDue");
     String emailBeforeDueDate1 = request.getParameter("emailBeforeDueDate1");
@@ -306,9 +319,21 @@
                 if ("emailEnableStudentPassFail".equals(fi.getFieldName())) {
                     emailEnableStudentPassFail = fi.getString();
                 }
-                if ("emailEnableManagerSummaryReport".equals(fi.getFieldName())) {
-                    emailEnableManagerSummaryReport = fi.getString();
+                if ("emailEnableManagerRecurReport".equals(fi.getFieldName())) {
+                    emailEnableManagerRecurReport = fi.getString();
                 }
+                if ("recurReportFreq".equals(fi.getFieldName())) {
+                    recurReportFreq = fi.getString();
+                }
+                if ("recurReportDay".equals(fi.getFieldName())) {
+                    recurReportDay = fi.getString();
+                }
+                if ("recurReportDayOfMonth".equals(fi.getFieldName())) {
+                    recurReportDayOfMonth = fi.getString();
+                }
+                if ("recurReportNumDays".equals(fi.getFieldName())) {
+                    recurReportNumDays = fi.getString();
+                }
                 if ("emailEnableBeforeDue".equals(fi.getFieldName())) {
                     emailEnableBeforeDue = fi.getString();
                 }
@@ -575,6 +600,34 @@
         		currentSRLengthVal = srLengthVal;
         	}
         }
+        if (recurReportFreq != null) {
+        	if (!recurReportFreq.equals(currentRecurReportFreq)) {
+        		saveSysconfig = true;
+        		sysConfigProperties.setProperty("RecurReportFreq", recurReportFreq);
+        		currentRecurReportFreq = recurReportFreq;
+        	}
+        }
+        if (recurReportDay != null) {
+        	if (!recurReportDay.equals(Integer.toString(currentRecurReportDay))) {
+        		saveSysconfig = true;
+        		sysConfigProperties.setProperty("RecurReportDay", recurReportDay);
+        		try { currentRecurReportDay = Integer.parseInt(recurReportDay); } catch(Exception e) {}
+        	}
+        }
+        if (recurReportDayOfMonth != null) {
+        	if (!recurReportDayOfMonth.equals(currentRecurReportDayOfMonth)) {
+        		saveSysconfig = true;
+        		sysConfigProperties.setProperty("RecurReportDayOfMonth", recurReportDayOfMonth);
+        		currentRecurReportDayOfMonth = recurReportDayOfMonth;
+        	}
+        }
+        if (recurReportNumDays != null) {
+        	if (!recurReportNumDays.equals(currentRecurReportNumDays)) {
+        		saveSysconfig = true;
+        		sysConfigProperties.setProperty("RecurReportNumDays", recurReportNumDays);
+        		currentRecurReportNumDays = recurReportNumDays;
+        	}
+        }
         if (alternativeLoginValidationEnable == null) { alternativeLoginValidationEnable = "off"; }
        	if (!alternativeLoginValidationEnable.equals(currentAlternativeLoginValidationEnable)) {
        		saveSysconfig = true;
@@ -667,11 +720,11 @@
        		sysConfigProperties.setProperty("EmailEnableStudentPassFail", emailEnableStudentPassFail);
        		currentEmailEnableStudentPassFail = emailEnableStudentPassFail;
        	}
-        if (emailEnableManagerSummaryReport == null) { emailEnableManagerSummaryReport = "off"; }
-       	if (!emailEnableManagerSummaryReport.equals(currentEmailEnableManagerSummaryReport)) {
+        if (emailEnableManagerRecurReport == null) { emailEnableManagerRecurReport = "off"; }
+       	if (!emailEnableManagerRecurReport.equals(currentEmailEnableManagerRecurReport)) {
        		saveSysconfig = true;
-       		sysConfigProperties.setProperty("EmailEnableManagerSummaryReport", emailEnableManagerSummaryReport);
-       		currentEmailEnableManagerSummaryReport = emailEnableManagerSummaryReport;
+       		sysConfigProperties.setProperty("EmailEnableManagerRecurReport", emailEnableManagerRecurReport);
+       		currentEmailEnableManagerRecurReport = emailEnableManagerRecurReport;
        	}
         int logSize = 0;
         int logKeep = 0;
@@ -861,6 +914,7 @@
 
 <link href="lms_style.css" rel="stylesheet" type="text/css" />
 <script type="text/javascript" src="crosswire.js"></script>
+<script type="text/javascript" src="js/jquery/jquery.min.js"></script>
 <script type="text/javascript">
 <!--
 function confirmSubmit(form, boxid) {
@@ -887,8 +941,35 @@
 
 function initPage() {
 	setTemplateVisible(0);
+	showRecurFreqDetail();
+	$('.recurMore').hide();
 }
 
+function showRecurFreqDetail() {
+	if ($('#recurReportFreq').val() == 'DAILY') {
+		$('.recurDay').hide();
+		$('.recurDayMonth').hide();
+	}
+	else if ($('#recurReportFreq').val() == 'WEEKLY') {
+		$('.recurDay').show();
+		$('.recurDayMonth').hide();
+	}
+	else if ($('#recurReportFreq').val() == 'MONTHLY') {
+		$('.recurDay').hide();
+		$('.recurDayMonth').show();
+	}
+}
+function showMoreRecurReport() {
+	if ($('.recurMore:first').is(":visible")) {
+		$('#moreRecurReport').html('▶ Details...');
+		$('.recurMore').hide();
+	}
+	else {
+		$('#moreRecurReport').html('▼ Details...');
+		$('.recurMore').show();
+	}
+}
+
 // -->
 </script>
 </head>
@@ -903,7 +984,7 @@
 <span class="instructiontxt"><%= statusMsg %></span><br/>
 <span class="instructiontxt"><%= validError %></span>
 </div>
-<form id="systemsave" method="post" action="admin_systemmanagement.jsp" enctype="multipart/form-data">
+<form autocomplete="false" id="systemsave" method="post" action="admin_systemmanagement.jsp" enctype="multipart/form-data">
 	<table cellpadding="0" id="tableForm" class="tableForm">
 	<tr>
 	      <th>Edit System Settings</th>
@@ -1011,11 +1092,18 @@
 	                            </tr>
 	                            <tr>
 	                              <td class="formHeadings">Outgoing Mail User: </td>
-	                              <td colspan="2"><input name="sendMailUser" type="text" value="<%=currentSendMailUser%>" size="40" autocomplete="off"/>                              </td>
-	                            </tr>
+	                              <td colspan="2">
+<!-- the following two hidden fields are to try to prevent chrome from autofilling empty web server login fields with user's standard username and password.  Stupid Chrome doesn't obey autocompete="false"
+these two fields get autofilled instead and are always ignored
+ -->
+<input name="prevent_autofill" type="text" value="" style="display:none;" />
+<input name="prevent_autofill_password" type="password" value="" style="display:none;" />
+<!-- end of stupid 2 dummy field workaround for Chrome -->
+
+<input name="sendMailUser" type="text" value="<%=currentSendMailUser%>" size="40" autocomplete="false"/> </td> </tr>
 	                            <tr>
 	                              <td class="formHeadings">Outgoing Mail Password: </td>
-	                              <td colspan="2"><input name="sendMailPasswd" type="password" value="<%=currentSendMailPasswd%>" size="40" autocomplete="off"/>                              </td>
+	                              <td colspan="2"><input name="sendMailPasswd" type="password" value="<%=currentSendMailPasswd%>" size="40" autocomplete="false"/>                              </td>
 	                            </tr>
 	                            <tr>
 	                              <td class="formHeadings">Default "From" Email Address: </td>
@@ -1054,10 +1142,6 @@
 	                              <td colspan="2"><input name="emailEnableStudentPassFail" type="checkbox" value="on" <%="on".equals(currentEmailEnableStudentPassFail)?"checked=\"checked\"":""%> size="40"/>Student Pass/Fail</td>
 	                            </tr>
 	                            <tr>
-	                              <td class="formHeadings"></td>
-	                              <td colspan="2"><input name="emailEnableManagerSummaryReport" type="checkbox" value="on" <%="on".equals(currentEmailEnableManagerSummaryReport)?"checked=\"checked\"":""%> size="40"/><t:t>Manager</t:t> Summary Report</td>
-	                            </tr>
-	                            <tr>
 	                              <td>&nbsp;</td>
 	                              <td colspan="2">&nbsp;</td>
 	                            </tr>
@@ -1077,12 +1161,52 @@
 	                              <td class="formHeadings"></td>
 	                              <td colspan="2"><input name="emailEnableAssignedRetakes" type="checkbox" value="on" <%="on".equals(currentEmailEnableAssignedRetakes)?"checked=\"checked\"":""%> size="40"/>Assigned Retakes</td>
 	                            </tr>
+                                <tr>
+                                    <td>Enable Manager Email Reports</td>
+                                    <td colspan='2'>&nbsp;</td>
+                                </tr>
 	                            <tr>
+	                              <td class="formHeadings"></td>
+	                              <td colspan="2"><input name="emailEnableManagerRecurReport" type="checkbox" value="on" <%="on".equals(currentEmailEnableManagerRecurReport)?"checked=\"checked\"":""%> size="40"/><t:t>Manager</t:t> Recurrent Training Report &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="cursor:pointer;" onclick="showMoreRecurReport();" id="moreRecurReport">▶ Details...</span></td>
+	                            </tr>
+	                            <tr class="recurMore">
+					<td class="formHeadings"></td>
+					<td>Frequency: </td>
+				    </tr>
+				    <tr class="recurMore">
+					<td class="formHeadings"></td>
+					<td>
+				                    <select onchange="showRecurFreqDetail();" id="recurReportFreq" name="recurReportFreq">
+				                      <option value="DAILY" <%="DAILY".equals(currentRecurReportFreq)?"selected=\"selected\"":""%>>Daily</option>
+				                      <option value="WEEKLY" <%="WEEKLY".equals(currentRecurReportFreq)?"selected=\"selected\"":""%>>Weekly</option>
+				                      <option value="MONTHLY"  <%="MONTHLY".equals(currentRecurReportFreq)?"selected=\"selected\"":"" %>>Monthly</option>
+				                    </select>
+					</td><td>
+						<table><tbody>
+							<tr class="recurDay"><td style="text-align:center;">S</td><td style="text-align:center;">M</td><td style="text-align:center;">T</td><td style="text-align:center;">W</td><td style="text-align:center;">T</td><td style="text-align:center;">F</td><td style="text-align:center;">S</td></tr>
+							<tr>
+								<td class="recurDay"><input name="recurReportDay" type="radio" value="<%=Calendar.SUNDAY%>" <%=Calendar.SUNDAY == currentRecurReportDay?"checked=\"checked\"":""%>/></td>
+								<td class="recurDay"><input name="recurReportDay" type="radio" value="<%=Calendar.MONDAY%>" <%=Calendar.MONDAY == currentRecurReportDay?"checked=\"checked\"":""%>/></td>
+								<td class="recurDay"><input name="recurReportDay" type="radio" value="<%=Calendar.TUESDAY%>" <%=Calendar.TUESDAY == currentRecurReportDay?"checked=\"checked\"":""%>/></td>
+								<td class="recurDay"><input name="recurReportDay" type="radio" value="<%=Calendar.WEDNESDAY%>" <%=Calendar.WEDNESDAY == currentRecurReportDay?"checked=\"checked\"":""%>/></td>
+								<td class="recurDay"><input name="recurReportDay" type="radio" value="<%=Calendar.THURSDAY%>" <%=Calendar.THURSDAY == currentRecurReportDay?"checked=\"checked\"":""%>/></td>
+								<td class="recurDay"><input name="recurReportDay" type="radio" value="<%=Calendar.FRIDAY%>" <%=Calendar.FRIDAY == currentRecurReportDay?"checked=\"checked\"":""%>/></td>
+								<td class="recurDay"><input name="recurReportDay" type="radio" value="<%=Calendar.SATURDAY%>" <%=Calendar.SATURDAY == currentRecurReportDay?"checked=\"checked\"":""%>/></td>
+								<td class="recurDayMonth">Send on: <input type="text" name="recurReportDayOfMonth" size="2" maxlength="2" value="<%=currentRecurReportDayOfMonth%>"/> Day of the Month</td>
+							</tr>
+						</tbody></table>
+					</td>
+	                            </tr>
+	                            <tr class="recurMore">
+	                              <td class="formHeadings"></td>
+	                              <td colspan="2">Include Upcoming Training for Next: <input type="text" name="recurReportNumDays" value="<%=currentRecurReportNumDays%>" size="4"/> Days</td>
+	                            </tr>
+	                            <tr>
 	                              <td>&nbsp;</td>
 	                              <td colspan="2">&nbsp;</td>
 	                            </tr>
 	                            <tr>
-	                              <td>Allow Users To Edit Their Email Address</td>
+	                              <td>Allow Users To Edit Their Email Address in My Profile</td>
 	                              <td colspan="2"><input name="emailEnableUserEdit" type="checkbox" value="on" <%="on".equals(currentEmailEnableUserEdit)?"checked=\"checked\"":""%> size="40"/></td>
 	                            </tr>
 	                            <tr>
@@ -1299,7 +1423,7 @@
 	    </table>
 </form>
 <br/>
-        <form id="announc" method="get" action="admin_systemmanagement.jsp">
+        <form autocomplete="false" id="announc" method="get" action="admin_systemmanagement.jsp">
                             <table cellpadding="0" cellspacing="0" class="tableMain">
                       <tr>
                         <th>Announcements</th>
@@ -1360,7 +1484,7 @@
           </table>
     </form>
         <br />
-        <form id="resourc" method="get" action="admin_systemmanagement.jsp">
+        <form autocomplete="false" id="resourc" method="get" action="admin_systemmanagement.jsp">
 
                     <table cellpadding="0" cellspacing="0" class="tableMain">
                       <tr>

Modified: branches/1.6/webapp/menu.jsp
===================================================================
--- branches/1.6/webapp/menu.jsp	2016-03-10 18:38:22 UTC (rev 1409)
+++ branches/1.6/webapp/menu.jsp	2016-03-10 18:44:41 UTC (rev 1410)
@@ -1,3 +1,36 @@
+<style type="text/css">
+    ul li{
+        display: inline-block;
+        position: relative;
+    }
+    ul li ul.dropdown{
+        padding: 0;
+        list-style: none;
+        display: none;
+        position: absolute;
+        z-index: 999;
+        left: 0;
+	background-image: url(images/bggradient.jpg);
+	background-position: left bottom;
+	background-size: 100% 100%;
+	background-repeat: repeat-x;
+    }
+    ul li:hover ul.dropdown{
+        display: block;	/* Display the dropdown */
+    }
+    ul li ul.dropdown li{
+        text-align: left;
+        display: block;
+	border-right: none !important;
+    }
+    ul li ul.dropdown li a{
+        display: block;
+        padding: 8px 8px;
+        color: #333;
+        text-decoration: none;
+    }
+</style>
+
    <div id="Banner"><span class="loggedinBar">Logged in as:<%=user.getUserProfileNum()%></span></div>
       <div id="MainMenu">
 <%
@@ -38,14 +71,30 @@
   }
   if ((user.getUserProfileAccessLevel() > UserProfile.ACCESS_MANAGER) || (user.hasAccess(UserProfile.ACCESS_MODE_MENU_STUDENT_RECORDS))) {
 %>
-	  <li><a href="admin_studentrecords.jsp">Student<br />Records</a></li>
+	<li><a href="#">Reports <span> &#9660;</span></a>
+	<ul class="dropdown">
 <%
   }
   if ((user.getUserProfileAccessLevel() > UserProfile.ACCESS_MANAGER) || (user.hasAccess(UserProfile.ACCESS_MODE_MENU_STUDENT_RECORDS))) {
 %>
-	  <li><a href="report_pending_summary.jsp">Summary<br />Report</a></li>
+	  <li><a href="admin_studentrecords.jsp">Student Records</a></li>
 <%
   }
+  if ((user.getUserProfileAccessLevel() > UserProfile.ACCESS_MANAGER) || (user.hasAccess(UserProfile.ACCESS_MODE_MENU_STUDENT_RECORDS))) {
+%>
+	  <li><a href="report_pending_summary.jsp">Summary Report</a></li>
+<%
+  }
+  if ((user.getUserProfileAccessLevel() > UserProfile.ACCESS_MANAGER) || (user.hasAccess(UserProfile.ACCESS_MODE_MENU_STUDENT_RECORDS))) {
+%>
+	  <li><a href="report_recurrent_training.jsp">Recurrent Training Report</a></li>
+<%
+  }
+  if (user.getUserProfileAccessLevel() >= UserProfile.ACCESS_MANAGER) {
+%>
+	</ul></li>
+<%
+  }
   if ((user.getUserProfileAccessLevel() > UserProfile.ACCESS_MANAGER) || (user.hasAccess(UserProfile.ACCESS_MODE_MENU_USER_PROFILE_MGMT))) {
 %>
 	  <li><a href="admin_profilemanagement.jsp">User Profile<br />Management</a></li>

Modified: branches/1.6/webapp/report_pending_summary.jsp
===================================================================
--- branches/1.6/webapp/report_pending_summary.jsp	2016-03-10 18:38:22 UTC (rev 1409)
+++ branches/1.6/webapp/report_pending_summary.jsp	2016-03-10 18:44:41 UTC (rev 1410)
@@ -115,7 +115,7 @@
 
     if ("csv".equals(action)) {
         noHTML = true;
-        response.setContentType("application/x-csv");
+        response.setContentType("text/csv");
         response.setHeader("Content-Disposition","attachment; filename=summaryReport.csv");
     }
    if ("lookup".equals(action)) {

Copied: branches/1.6/webapp/report_recurrent_training.jsp (from rev 1356, trunk/webapp/report_recurrent_training.jsp)
===================================================================
--- branches/1.6/webapp/report_recurrent_training.jsp	                        (rev 0)
+++ branches/1.6/webapp/report_recurrent_training.jsp	2016-03-10 18:44:41 UTC (rev 1410)
@@ -0,0 +1,375 @@
+<%@ page
+    language="java" contentType="text/html;charset=utf-8" %>
+<%@ page trimDirectiveWhitespaces="true" %>
+<%@ page import="com.resolutions.ils.*" %>
+<%@ page import="com.resolutions.ils.data.*" %>
+<%@ page import="java.util.Vector" %>
+<%@ page import="java.util.Comparator" %>
+<%@ page import="java.util.Date" %>
+<%@ page import="java.text.SimpleDateFormat" %>
+<%@ page import="org.apache.log4j.Logger" %>
+<%@ page import="java.util.Collections" %>
+ 
+<%
+	Logger logger = Logger.getLogger(this.getClass());
+    String statusMsg = "";
+    String validError = "";
+    int daysTilDue = 30;
+    String sortOrder = "past";
+    final ILSSession ilsSession = (ILSSession)session.getAttribute("ilsSession");
+    if (ilsSession == null) {
+        out.print("<html><head><META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;URL=login.jsp\"></head></html>");
+        return;
+    }
+
+    boolean noHTML = false;
+
+    UserProfile user = ilsSession.getCurrentUserProfile();
+    if ((user.getUserProfileAccessLevel() <= UserProfile.ACCESS_MANAGER) && (!user.hasAccess(UserProfile.ACCESS_MODE_MENU_STUDENT_RECORDS))) {
+        out.print("<html><body><h1>Access Forbidden</h1></body></html>");
+        Logger.getLogger(this.getClass()).info("Access denied to user ["+user.getUserProfileNum()+"]");
+        return;
+    }
+
+    int limitToManager = (user.getUserProfileAccessLevel() <= UserProfile.ACCESS_MANAGER) ? user.getUserProfileID() : -1;
+
+    try { daysTilDue = (Integer)session.getAttribute("daysTilDue"); } catch(Exception e) {}
+    try { daysTilDue = Integer.parseInt(request.getParameter("daysTilDue")); } catch(Exception e) {}
+    try { session.setAttribute("daysTilDue", new Integer(daysTilDue)); } catch(Exception e) {}
+
+    String val = (String)session.getAttribute("recurrentSort"); if (val != null) sortOrder = val;
+    val = (String)request.getParameter("sort"); if (val != null) sortOrder = val;
+    session.setAttribute("recurrentSort", sortOrder);
+
+    Vector<UserProfile> userProfiles = null;
+    SimpleDateFormat df  = new SimpleDateFormat("MM/dd/yyyy");
+    String action = request.getParameter("action");
+
+    String tmp;
+    final String sort = sortOrder;
+
+    if ("csv".equals(action)) {
+        noHTML = true;
+        response.setContentType("text/csv");
+        response.setHeader("Content-Disposition","attachment; filename=recurrentReport.csv");
+    }
+
+        userProfiles = UserProfile.getManagerRecurrentTrainingReport(ilsSession, daysTilDue, limitToManager);
+	int expiredCount = 0;
+	for (UserProfile up : userProfiles) {
+		if (up.getValue("DAYSEXPIRED") != null) ++expiredCount;
+	}
+        if (sort != null) {
+            Collections.sort(userProfiles, new Comparator() {
+                public int compare(Object o1, Object o2) {
+			UserProfile p1 = (UserProfile)o1;
+			UserProfile p2 = (UserProfile)o2;
+                    if ("lname".equals(sort)) {
+                        return p1.getUserProfileLastName().compareTo(p2.getUserProfileLastName());
+                    }
+                    if ("fname".equals(sort)) {
+                        return p1.getUserProfileFirstName().compareTo(p2.getUserProfileFirstName());
+                    }
+                    if ("empid".equals(sort)) {
+                        return p1.getUserProfileNum().compareTo(p2.getUserProfileNum());
+                    }
+                    if ("location".equals(sort)) {
+                        return p1.getWorkgroup(ilsSession).compareTo(p2.getWorkgroup(ilsSession));
+                    }
+                    if ("role".equals(sort)) {
+                        return p1.getRole(ilsSession).compareTo(p2.getRole(ilsSession));
+                    }
+                    if ("cname".equals(sort)) {
+                        return p1.getStringValue("COURSNAME").compareTo(p2.getStringValue("COURSNAME"));
+                    }
+                    if ("past".equals(sort)) {
+			return p2.getIntValue("DAYSEXPIRED") - p1.getIntValue("DAYSEXPIRED");
+                    }
+                    if ("due".equals(sort)) {
+                        Date d1 = p1.getDateValue("CAEXPIREDON");
+                        Date d2 = p2.getDateValue("CAEXPIREDON");
+                        long i1 = (d1 == null) ? 0 : d1.getTime();
+                        long i2 = (d2 == null) ? 0 : d2.getTime();
+                        return (i1 > i2) ? -1 : (i1 == i2) ? 0 : 1;
+                    }
+                    return 0;
+                }
+            });
+
+        }
+
+    if (!noHTML) {
+%>
+<!doctype html>
+<html>
+<head>
+<title><%= ilsSession.getCurrentCompany().getCompanyName() %> eLearning Portal</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
+	<link rel="stylesheet" href="css/chosen/chosen.min.css">
+	<script type="text/javascript" src="js/jquery/jquery.min.js"></script>
+	<script type="text/javascript" src="js/jquery/jquery.blockUI.js"></script>
+	<script type="text/javascript" src="js/chosen/chosen.jquery.min.js"></script>
+	<script type="text/javascript" src="crosswire.js"></script>
+	<link href="lms_style.css" rel="stylesheet" type="text/css"/>
+	<script type="text/javascript" language="JavaScript">
+<!--
+var rdCtl = null;
+
+function rD(val) {
+    rdCtl.value = val;
+}
+
+function scrollToReport() {
+	records = document.getElementById("gotRecords")
+	if (records) {
+		window.location.hash="report";
+	}
+}
+
+$(document).ready(function() {
+	$('#locationSelect').attr('data-placeholder', $('#selectWorkgroup').text());
+	$('#roleSelect').attr('data-placeholder', $('#selectRole').text());
+	$('#roleSelect').chosen();
+	$('#locationSelect').chosen();
+});
+
+// -->
+    </script>
+   <!-- <style type="text/css">
+<!--
+<!--.style1 {font-size: 12px}
+<!--.style2 {text-transform: none; color: #3F7ABA; padding: 4px 4px 8px; font-weight: bold; text-decoration: none; border: none; font-family: Arial, Helvetica, sans-serif;}
+<!--.style3 {font-size: 10px}
+<!--.style6 {font-size: 12px; text-transform: none; font-weight: bold; text-decoration: none; border: none; font-family: Arial, Helvetica, sans-serif;}
+-->
+   <!-- </style>// -->
+   <style type="text/css">
+<!--
+.style1 {color: #9A9697}
+-->
+   </style>
+</head>
+
+<body onLoad="scrollToReport()">
+<%@ include file="header.jsp" %>
+  <div id="pageContainer">
+<%@ include file="menu.jsp" %>
+<div id="content">
+<div id="pageTitles">
+Recurrent Training Management Report<br />
+<span class="instructiontxt"><%= statusMsg %></span>
+<span class="instructiontxt"><%= validError %></span>
+                          <table class="tableBTN">
+                            <tr>
+                              <td class="tableBTN_td1">
+                                <table>
+                                  <tr>
+                                    <td><a href="javascript:void(window.print())" target="_top"><img border="0" src="images/print_btn.gif" width="24" height="24" alt=""/></a></td>
+                                    <td><a class="formButtons" href="javascript:void(window.print())" target="_top">Print Report</a></td>
+                                  </tr>
+                              </table>                              </td>
+                              <td>
+                                <table>
+                                  <tr>
+                                    <td><a href="?action=csv"><img border="0" src="images/download_btn.gif" width="24" height="24" alt=""></a></td>
+					<td></td>
+                                    <td><a href="?action=csv" class="formButtons">Download to Excel File </a></td>
+                                    <td><form action="#">View Upcoming Training Within The Next <input name="daysTilDue" size="5" value="<%=daysTilDue%>"/> Days <button>Go</button></form></td>
+                                  </tr>
+                                </table>
+                              </td>
+                            </tr>
+                          </table>
+</div>
+
+                    <table cellpadding="0" cellspacing="0" class="tableMain">
+                      <tr>
+                        <th>
+                        Past Due Training&nbsp; ( <%=expiredCount %> &nbsp;Records&nbsp;)  <%= (userProfiles.size()>0)?"<a name=\"report\" id=\"gotRecords\"></a>":"" %> </th>
+
+                      </tr>
+                      <tr>
+                        <td>
+                        </td>
+                      </tr>
+                      <tr>
+                        <td>
+                          <table class="tableDataList">
+                            <tr>
+                              <th><a href="?sort=lname">Last Name</a></th>
+                              <th><a href="?sort=fname">First Name</a></th>
+                              <th><a href="?sort=empid">Emp ID</a></th>
+                              <th><a href="?sort=location"><t:t>Workgroup</t:t></a></th>
+                              <th><a href="?sort=role"><t:t>Role</t:t></a></th>
+                              <th><a href="?sort=course">Course Name</a></th>
+                              <th><a href="?sort=due">Date Due</a></th>
+                              <th><a href="?sort=past">Days Past Due</a></th>
+                            </tr>
+<%
+    }
+    else {
+	out.print(ilsSession.getCurrentCompany().getCompanyName() + "\n");
+	out.print(user.getUserProfileFirstName() + " " + user.getUserProfileLastName() + "\n");
+	out.print("Report Run " + df.format(new Date()) + "\n\n");
+	out.print("Recurrent Training Management Report\n\n");
+	out.print("Past Due Training\n\n");
+        out.print("Last Name,");
+	out.print("First Name,");
+	out.print("Emp ID,");
+%><t:t>Workgroup</t:t>,<%
+%><t:t>Role</t:t>,<%
+	out.print("Course Name,Date Due,Days Past Due\n");
+    }
+    for (UserProfile up : userProfiles) {
+	 if (up.getValue("DAYSEXPIRED") == null) continue;
+         Date lastDate = up.getDateValue("CAEXPIREDON");
+         String eDate = (lastDate != null) ? df.format(lastDate) : "";
+         if (!noHTML) {
+             %>
+             <tr>
+                 <td><a href="report_employeecourseatt.jsp?profileid=<%=up.getUserProfileID()%>"><%=up.getUserProfileLastName()%></a></td>
+                 <td><a href="report_employeecourseatt.jsp?profileid=<%=up.getUserProfileID()%>"><%=up.getUserProfileFirstName()%></a></td>
+                 <td><a href="report_employeecourseatt.jsp?profileid=<%=up.getUserProfileID()%>"><%=up.getUserProfileNum()%></a></td>
+<%
+	String workgroup  = up.getWorkgroup(ilsSession);
+	String workgroupSet = up.getWorkgroups(ilsSession);
+	if (!workgroup.equals(workgroupSet)) workgroup += " ...";
+%>
+		<td title="<%= workgroupSet %>"><%= workgroup %></td>
+<%
+	String role = up.getRole(ilsSession);
+	String roleSet = up.getRoles(ilsSession);
+	if (!role.equals(roleSet)) role += " ...";
+%>
+		<td title="<%= roleSet %>"><%= role %></td>
+                 <td width="60" align="right"><%=up.getStringValue("COURSNAME")%></td>
+                 <td width="75" align="right"><%=eDate%></td>
+                 <td width="60" align="right"><%=up.getIntValue("DAYSEXPIRED")%></td>
+             </tr>
+             <%
+         }
+         else {
+		out.print("\""+up.getUserProfileLastName().replaceAll("\"", "\"\"") + "\",");
+		out.print("\""+up.getUserProfileFirstName().replaceAll("\"", "\"\"") + "\",");
+		out.print("\""+up.getUserProfileNum().replaceAll("\"", "\"\"") + "\",");
+		out.print("\""+up.getWorkgroups(ilsSession).replaceAll("\"", "\"\"") + "\",");
+		out.print("\""+up.getRoles(ilsSession).replaceAll("\"", "\"\"") + "\",");
+		out.print(up.getStringValue("COURSNAME") + ",");
+		out.print(eDate + ",");
+		out.print(up.getIntValue("DAYSEXPIRED") + ",");
+		out.print("\n");
+         }
+    }
+    if (!noHTML) {
+%>
+                        </table></td>
+                      </tr>
+    </table>
+                    <table cellpadding="0" cellspacing="0" class="tableMain">
+                      <tr>
+                        <th>
+                        Training Required Next <%=daysTilDue%> Days&nbsp; ( <%=userProfiles.size() - expiredCount %> &nbsp;Records&nbsp;)  <%= (userProfiles.size()>0)?"<a name=\"report\" id=\"gotRecords\"></a>":"" %> </th>
+
+                      </tr>
+                      <tr>
+                        <td>
+                        </td>
+                      </tr>
+                      <tr>
+                        <td>
+                          <table class="tableDataList">
+                            <tr>
+                              <th><a href="?sort=lname">Last Name</a></th>
+                              <th><a href="?sort=fname">First Name</a></th>
+                              <th><a href="?sort=empid">Emp ID</a></th>
+                              <th><a href="?sort=location"><t:t>Workgroup</t:t></a></th>
+                              <th><a href="?sort=role"><t:t>Role</t:t></a></th>
+                              <th><a href="?sort=course">Course Name</a></th>
+                              <th><a href="?sort=due">Date Due</a></th>
+                              <th><a href="?sort=past">Days to Due Date</a></th>
+                            </tr>
+<%
+    }
+    else {
+	out.print("\n\nTraining Required Next " + daysTilDue+" Days\n\n");
+        out.print("Last Name,");
+	out.print("First Name,");
+	out.print("Emp ID,");
+%><t:t>Workgroup</t:t>,<%
+%><t:t>Role</t:t>,<%
+	out.print("Course Name,Date Due,Days to Due Date\n");
+    }
+	if ("past".equals(sort)) {
+            Collections.sort(userProfiles, new Comparator() {
+                public int compare(Object o1, Object o2) {
+			UserProfile p1 = (UserProfile)o1;
+			UserProfile p2 = (UserProfile)o2;
+			return p1.getIntValue("DAYSSHOULDEXPIRE") - p2.getIntValue("DAYSSHOULDEXPIRE");
+                }
+            });
+
+        }
+    for (UserProfile up : userProfiles) {
+	 if (up.getValue("DAYSEXPIRED") != null) continue;
+         Date lastDate = up.getDateValue("CAEXPIREDON");
+         String eDate = (lastDate != null) ? df.format(lastDate) : "";
+         if (!noHTML) {
+             %>
+             <tr>
+                 <td><a href="report_employeecourseatt.jsp?profileid=<%=up.getUserProfileID()%>"><%=up.getUserProfileLastName()%></a></td>
+                 <td><a href="report_employeecourseatt.jsp?profileid=<%=up.getUserProfileID()%>"><%=up.getUserProfileFirstName()%></a></td>
+                 <td><a href="report_employeecourseatt.jsp?profileid=<%=up.getUserProfileID()%>"><%=up.getUserProfileNum()%></a></td>
+<%
+	String workgroup  = up.getWorkgroup(ilsSession);
+	String workgroupSet = up.getWorkgroups(ilsSession);
+	if (!workgroup.equals(workgroupSet)) workgroup += " ...";
+%>
+		<td title="<%= workgroupSet %>"><%= workgroup %></td>
+<%
+	String role = up.getRole(ilsSession);
+	String roleSet = up.getRoles(ilsSession);
+	if (!role.equals(roleSet)) role += " ...";
+%>
+		<td title="<%= roleSet %>"><%= role %></td>
+                 <td width="60" align="right"><%=up.getStringValue("COURSNAME")%></td>
+                 <td width="75" align="right"><%=eDate%></td>
+                 <td width="60" align="right"><%=up.getIntValue("DAYSSHOULDEXPIRE")%></td>
+             </tr>
+             <%
+         }
+         else {
+		out.print("\""+up.getUserProfileLastName().replaceAll("\"", "\"\"") + "\",");
+		out.print("\""+up.getUserProfileFirstName().replaceAll("\"", "\"\"") + "\",");
+		out.print("\""+up.getUserProfileNum().replaceAll("\"", "\"\"") + "\",");
+		out.print("\""+up.getWorkgroups(ilsSession).replaceAll("\"", "\"\"") + "\",");
+		out.print("\""+up.getRoles(ilsSession).replaceAll("\"", "\"\"") + "\",");
+		out.print(up.getStringValue("COURSNAME") + ",");
+		out.print(eDate + ",");
+		out.print(up.getIntValue("DAYSSHOULDEXPIRE") + ",");
+		out.print("\n");
+         }
+    }
+    if (!noHTML) {
+%>
+                        </table></td>
+                      </tr>
+    </table>
+
+<%
+  }
+if (!noHTML) {
+%>
+
+<div id="attributeTranslationStrings" style="display:none;">
+<span id="selectWorkgroup"><t:t>Select Workgroup</t:t></span>
+<span id="selectRole"><t:t>Select Role</t:t></span>
+</div>
+
+</div>
+<%@ include file="footer.jsp" %>
+</div>
+
+</body>
+</html>
+
+<%} %>




More information about the Ils-source mailing list