[Ils-source] r1373 - in trunk: 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
Wed Jan 6 10:34:23 MST 2016


Author: scribe
Date: 2016-01-06 10:34:23 -0700 (Wed, 06 Jan 2016)
New Revision: 1373

Added:
   trunk/db/mssql/upgrade185.1.sql
   trunk/src/com/resolutions/jobs/MgrRecurEMails.java
Modified:
   trunk/db/mssql/ilsdb.sql
   trunk/src/com/resolutions/ils/data/Group.java
   trunk/src/com/resolutions/ils/data/UserProfile.java
   trunk/webapp/WEB-INF/classes/jobs.xml
   trunk/webapp/WEB-INF/lib/crosswire-integration.jar
   trunk/webapp/WEB-INF/lib/crosswire.jar
   trunk/webapp/admin_groupmanagement.jsp
   trunk/webapp/admin_profile.jsp
   trunk/webapp/admin_studentrecords.jsp
   trunk/webapp/admin_systemmanagement.jsp
   trunk/webapp/report_pending_summary.jsp
   trunk/webapp/report_recurrent_training.jsp
Log:
added new database field required for manager override of recurrent training email reports
added db upgrade script for new field required for manager override of recurrent training email reports
moved commands to the end of the db create script which need to be run seperately
Added new getManagers call to UserProfile
Added new getManagerRecurrentTrainingReport call to UserProfile
Added new property for overriding manager recurrent training emails to UserProfile
Added a non-static getRoles method and getWorgroups method to UserProfile
Added a method to send the email for recurrent training report to a manager UserProfile
Added a getUserGroups methos to Group which doesn't require a session
Added new schedule job for manager recurrent emails
Added configuration options to system management panel for manager recurrent training emails
Changed group iteration to typesafe call in admin_groupmanagement screen
Changed csv output to use correct mime type
Fixed paging limit in crosswire.jar
Added option in user profile screen to override recurrent emails
First cut of finished recurrent training reports with scheduler


Modified: trunk/db/mssql/ilsdb.sql
===================================================================
--- trunk/db/mssql/ilsdb.sql	2016-01-05 19:58:28 UTC (rev 1372)
+++ trunk/db/mssql/ilsdb.sql	2016-01-06 17:34:23 UTC (rev 1373)
@@ -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);

Added: trunk/db/mssql/upgrade185.1.sql
===================================================================
--- trunk/db/mssql/upgrade185.1.sql	                        (rev 0)
+++ trunk/db/mssql/upgrade185.1.sql	2016-01-06 17:34:23 UTC (rev 1373)
@@ -0,0 +1 @@
+alter table USERPROFILE add USERPMGRRECUREMAILSOVERRIDE char(1) DEFAULT 'F';

Modified: trunk/src/com/resolutions/ils/data/Group.java
===================================================================
--- trunk/src/com/resolutions/ils/data/Group.java	2016-01-05 19:58:28 UTC (rev 1372)
+++ trunk/src/com/resolutions/ils/data/Group.java	2016-01-06 17:34:23 UTC (rev 1373)
@@ -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: trunk/src/com/resolutions/ils/data/UserProfile.java
===================================================================
--- trunk/src/com/resolutions/ils/data/UserProfile.java	2016-01-05 19:58:28 UTC (rev 1372)
+++ trunk/src/com/resolutions/ils/data/UserProfile.java	2016-01-06 17:34:23 UTC (rev 1373)
@@ -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,7 @@
 	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.USERPRID, CASS.COURSID, UP.USERPRLNAME, UP.USERPRFNAME, UP.USERPRNUM, "
+	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;
@@ -407,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, " +
@@ -503,13 +530,20 @@
         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 limitToManagerID) {
+	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(session.getCompanyID());
+		retVal.setCompanyID(companyID);
 		retVal.setIntValue("DAYSTILEXP", daysTilExpire);
 		if (limitToManagerID != -1) {
 			sql += RECURRENT_TRAINING_REPORT_LIMIT_TO_MANAGER;
@@ -709,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");
     }
@@ -765,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) {
@@ -785,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) {
@@ -915,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);
 	}

Added: trunk/src/com/resolutions/jobs/MgrRecurEMails.java
===================================================================
--- trunk/src/com/resolutions/jobs/MgrRecurEMails.java	                        (rev 0)
+++ trunk/src/com/resolutions/jobs/MgrRecurEMails.java	2016-01-06 17:34:23 UTC (rev 1373)
@@ -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: trunk/webapp/WEB-INF/classes/jobs.xml
===================================================================
--- trunk/webapp/WEB-INF/classes/jobs.xml	2016-01-05 19:58:28 UTC (rev 1372)
+++ trunk/webapp/WEB-INF/classes/jobs.xml	2016-01-06 17:34:23 UTC (rev 1373)
@@ -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: trunk/webapp/WEB-INF/lib/crosswire-integration.jar
===================================================================
(Binary files differ)

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

Modified: trunk/webapp/admin_groupmanagement.jsp
===================================================================
--- trunk/webapp/admin_groupmanagement.jsp	2016-01-05 19:58:28 UTC (rev 1372)
+++ trunk/webapp/admin_groupmanagement.jsp	2016-01-06 17:34:23 UTC (rev 1373)
@@ -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: trunk/webapp/admin_profile.jsp
===================================================================
--- trunk/webapp/admin_profile.jsp	2016-01-05 19:58:28 UTC (rev 1372)
+++ trunk/webapp/admin_profile.jsp	2016-01-06 17:34:23 UTC (rev 1373)
@@ -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");
@@ -273,9 +275,11 @@
                 // modifying an existing user
 		if (orig.getUserProfileID() > 0) {
 			String oldGroups = "";
-			for (int cg : currentRoles) {
-				if (oldGroups.length() > 0) oldGroups += ", ";
-				oldGroups += cg;
+			if (currentRoles != null) {
+				for (int cg : currentRoles) {
+					if (oldGroups.length() > 0) oldGroups += ", ";
+					oldGroups += cg;
+				}
 			}
 			eventsLogger.info("User " + current.getUserProfileNum() + " ROLES changed from " + oldGroups + " to " + newGroups + " by user: " + ilsSession.getCurrentUserProfile().getUserProfileNum());
                 }
@@ -291,9 +295,11 @@
                 // modifying an existing user
 		if (orig.getUserProfileID() > 0) {
 			String oldGroups = "";
-			for (int cg : currentLocations) {
-				if (oldGroups.length() > 0) oldGroups += ", ";
-				oldGroups += cg;
+			if (currentLocations != null) {
+				for (int cg : currentLocations) {
+					if (oldGroups.length() > 0) oldGroups += ", ";
+					oldGroups += cg;
+				}
 			}
 			eventsLogger.info("User " + current.getUserProfileNum() + " WORKGROUPS changed from " + oldGroups + " to " + newGroups + " by user: " + ilsSession.getCurrentUserProfile().getUserProfileNum());
                 }
@@ -571,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>

Modified: trunk/webapp/admin_studentrecords.jsp
===================================================================
--- trunk/webapp/admin_studentrecords.jsp	2016-01-05 19:58:28 UTC (rev 1372)
+++ trunk/webapp/admin_studentrecords.jsp	2016-01-06 17:34:23 UTC (rev 1373)
@@ -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: trunk/webapp/admin_systemmanagement.jsp
===================================================================
--- trunk/webapp/admin_systemmanagement.jsp	2016-01-05 19:58:28 UTC (rev 1372)
+++ trunk/webapp/admin_systemmanagement.jsp	2016-01-06 17:34:23 UTC (rev 1373)
@@ -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>
@@ -1078,6 +1162,42 @@
 	                              <td colspan="2"><input name="emailEnableAssignedRetakes" type="checkbox" value="on" <%="on".equals(currentEmailEnableAssignedRetakes)?"checked=\"checked\"":""%> size="40"/>Assigned Retakes</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>
@@ -1299,7 +1419,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 +1480,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: trunk/webapp/report_pending_summary.jsp
===================================================================
--- trunk/webapp/report_pending_summary.jsp	2016-01-05 19:58:28 UTC (rev 1372)
+++ trunk/webapp/report_pending_summary.jsp	2016-01-06 17:34:23 UTC (rev 1373)
@@ -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)) {

Modified: trunk/webapp/report_recurrent_training.jsp
===================================================================
--- trunk/webapp/report_recurrent_training.jsp	2016-01-05 19:58:28 UTC (rev 1372)
+++ trunk/webapp/report_recurrent_training.jsp	2016-01-06 17:34:23 UTC (rev 1373)
@@ -50,7 +50,7 @@
 
     if ("csv".equals(action)) {
         noHTML = true;
-        response.setContentType("application/x-csv");
+        response.setContentType("text/csv");
         response.setHeader("Content-Disposition","attachment; filename=recurrentReport.csv");
     }
 




More information about the Ils-source mailing list