Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
  • Loading branch information
clj13001 committed Apr 21, 2017
2 parents 260aad7 + 5e8ed1e commit 30999b4
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 67 deletions.
10 changes: 8 additions & 2 deletions WebContent/html/webpages/redirect/ticketAdminRedirect.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ int locationid = Integer.parseInt(locationidstr);
//approve form was submitted
if(request.getParameter("approve") != null){
//TODO include in time of action so that the status fields can be updated in the ticket
TicketQueries.acceptTicket(ticketid,deviceid,locationid,Integer.parseInt(navsso));
User client = EmployeeQueries.getEmployeeByID(TicketQueries.getUserID(ticketid));
boolean notificationPreferences = (Math.floor(client.getNotificationPreferences()/2)%2==1);
//The second least significant bit of notificationPreferences - the 4's place - is used for ticket approval notifications.
//The second least significant bit of notificationPreferences - the 2's place - is used for ticket approval notifications.
if(notificationPreferences){
NotificationQueue q = new NotificationQueue(client,"ticketConfirmations");
q.start();
Expand All @@ -50,6 +49,13 @@ if(request.getParameter("approve") != null){
//reject form was submitted
if(request.getParameter("reject") != null){
TicketQueries.rejectTicket(ticketid);
User client = EmployeeQueries.getEmployeeByID(TicketQueries.getUserID(ticketid));
boolean notificationPreferences = (Math.floor(client.getNotificationPreferences()/4)%2==1);
//The third least significantbit of notificationPreferences - te 4's place - is used for ticket rejection notifications.
if(notificationPreferences){
NotificationQueue q = new NotificationQueue(client, "ticketRejections");
q.start();
}
}
%>
<script>
Expand Down
38 changes: 12 additions & 26 deletions src/database/TicketQueries.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,10 @@ public static void rejectTicket(int id)
Thread.sleep(1);
}
}
stmt.executeUpdate("UPDATE ticket SET Status = \"Rejected\" WHERE Ticket_ID = " + id);
long milliseconds = new Date().getTime();
String query="UPDATE ticket SET Status = \"Rejected\", Status_Date_Fields = "+milliseconds+" WHERE Ticket_ID = " + id;
System.out.println("Executing query "+query);
stmt.executeUpdate(query);
stmt.close();
connection.close();
}
Expand Down Expand Up @@ -211,36 +214,18 @@ public static long getLatestTicketActivity(User employee, String status)
connection.close();
return results.getLong("MAX(Status_Date_Fields)");
}
// Returns all tickets approved since 'millieconds' and associated with 'employee'
public static Ticket[] getRecentApprovedTickets(int userID, long milliseconds)
throws SQLException, ClassNotFoundException, InterruptedException {

// Returns all tickets changed to 'status' since 'millieconds' and associated with 'employee'
public static Ticket[] getRecentlyChangedTickets(int userID, String status, long milliseconds) throws SQLException, ClassNotFoundException {
System.getenv("VCAP_SERVICES");
Class.forName("com.mysql.jdbc.Driver");
Connection connection;
Statement stmt;
for(;;){
try{
connection = DriverManager.getConnection(database, user, password);
break;
}
catch(SQLException e){
Thread.sleep(1);
}
}
for(;;){
try{
stmt = connection.createStatement();
break;
}
catch(SQLException e){
Thread.sleep(1);
}
}
Connection connect = DriverManager.getConnection(database, user, password);
Statement stmt = connect.createStatement();
String query= "SELECT ticket.*, employee.Name AS 'username', devices.Device_Name, location.Name AS 'locationname' "
+"FROM ticket INNER JOIN employee ON ticket.Requestor = employee.Employee_ID "
+"INNER JOIN devices ON ticket.Device_ID = devices.Device_ID "
+"INNER JOIN location ON ticket.Location = location.Location_ID "
+"WHERE ticket.Status = 'Approved' AND Requestor = " + userID
+"WHERE ticket.Status = '"+status+"' AND Requestor = " + userID
+" AND Status_Date_Fields >= " + milliseconds;
System.out.println("Executing query '"+query+"'");
ResultSet results = stmt.executeQuery(query);
Expand All @@ -266,9 +251,10 @@ public static Ticket[] getRecentApprovedTickets(int userID, long milliseconds)
i++;
}
stmt.close();
connection.close();
connect.close();
return tickets;
}

public static int getUserID(int ticketID) throws ClassNotFoundException, SQLException, InterruptedException{
System.getenv("VCAP_SERVICES");
Class.forName("com.mysql.jdbc.Driver");
Expand Down
95 changes: 72 additions & 23 deletions src/utilities/Mail.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public class Mail {
private String sender = "Senior.design.synchrony.test@gmail.com";
private String password = "synchrony123";
private User client;
private String profileLink = "https://seniordesign.cfapps.io/html/webpages/profileSettings.jsp";
private String ticketLink = "";

public Mail(User client){
this.client=client;
}
Expand All @@ -29,16 +32,16 @@ public void sendTicketConfirmation(int[] ticketIDs) throws IOException, Interrup
String subject = "Your test device order";
// I really want to read this from a seperate file, but even when it's in the same directory eclipse insists on moving everything around :(
String msg = "<!DOCTYPE html>"
+ "<html>"
+ "<body>"
+ "<h4>We've received your order! We'll let you know when your device{s} ship{!s}.</h4>"
+ "<p>The following ticket{s} {was/were} generated:</p>"
+ "<div name = 'tickets' style='text-indent: 20px'>"
+ "{TICKETS GO HERE}"
+ "</div>"
+ "</body>"
+ "<footer style='text-align: center;'><font size='1'>To change notification settings, please visit your <a href='../WebContent/html/webpages/profileSettings.jsp'>profile settings page</a></font></footer>"
+ "</html>";
+ "<html>"
+ "<body>"
+ "<h4>We've received your order! We'll let you know when your device{s} ship{!s}.</h4>"
+ "<p>The following ticket{s} {was/were} generated:</p>"
+ "<div name = 'tickets' style='text-indent: 20px'>"
+ "{TICKETS GO HERE}"
+ "</div>"
+ "</body>"
+ "<footer style='text-align: center;'><font size='1'>To change notification settings, please visit your <a href='"+profileLink+"'>profile settings page</a></font></footer>"
+ "</html>";

// The messege needs to be tailored to make sense
msg=msg.replace("{s}",(ticketIDs.length==1 ? "" : "s")); //make occurances of 'device' and 'ticket' plural or singular
Expand All @@ -47,7 +50,7 @@ public void sendTicketConfirmation(int[] ticketIDs) throws IOException, Interrup
String tickethtml = "";
for(int tickID : ticketIDs)
{
tickethtml+="<p>Ticket #<a href='../WebContent/html/webpages/'>"+tickID+"</a></p>";
tickethtml+="<p>Ticket #<a href='"+ticketLink+"'>"+tickID+"</a></p>";
}
msg=msg.replace("{TICKETS GO HERE}",tickethtml);
Properties properties = System.getProperties();
Expand Down Expand Up @@ -78,17 +81,17 @@ protected PasswordAuthentication getPasswordAuthentication(){
public void sendTicketApproval(Ticket[] tickets) throws IOException, InterruptedException {
String subject = "{DEVICE(S)} {is/are(3)} on the way!";
String messege = "<!DOCTYPE html>"
+ "<html>"
+ "<body>"
+ "<h4>Your ticket{s} {have/has} been approved!</h4>"
+ "<p>I hope you're exicted, because the device{s} you ordered {is/are} about to ship. Happy testing!</p>"
+ "{list_header}"
+ "<div name = 'tickets' style='text-indent: 20px'>"
+ "{TICKETS GO HERE}"
+ "</div>"
+ "</body>"
+ "<footer style='text-align: center;'><font size='1'>To change notification settings, please visit your <a href='../WebContent/html/webpages/profileSettings.jsp'>profile settings page</a></font></footer>"
+ "</html>";
+ "<html>"
+ "<body>"
+ "<h4>Your ticket{s} {have/has} been approved!</h4>"
+ "<p>I hope you're exicted, because the device{s} you ordered {is/are} about to ship. Happy testing!</p>"
+ "{list_header}"
+ "<div name = 'tickets' style='text-indent: 20px'>"
+ "{TICKETS GO HERE}"
+ "</div>"
+ "</body>"
+ "<footer style='text-align: center;'><font size='1'>To change notification settings, please visit your <a href='"+profileLink+"'>profile settings page</a></font></footer>"
+ "</html>";

subject=subject.replace("{DEVICE(S)}", tickets[0].getDeviceName() + (tickets.length>1 ? " and "+(tickets.length-1)+" more" : ""));
subject=subject.replace("{is/are(3)}",tickets.length>2 ? "are" : "is");
Expand All @@ -100,7 +103,7 @@ public void sendTicketApproval(Ticket[] tickets) throws IOException, Interrupted
if(tickets.length>1)
{
for (Ticket tic : tickets) {
ticketList+="<p>Ticket #<a href='../WebContent/html/webpages/'>"+tic.getId()+"</a> - "+tic.getDeviceName()+"</p>";
ticketList+="<p>Ticket #<a href='"+ticketLink+"'>"+tic.getId()+"</a> - "+tic.getDeviceName()+"</p>";
}
}
messege=messege.replace("{TICKETS GO HERE}",ticketList);
Expand All @@ -127,6 +130,52 @@ protected PasswordAuthentication getPasswordAuthentication(){
mex.printStackTrace();
}
}

public void sendTicketRejection(Ticket[] tickets) throws IOException, InterruptedException{
String subject = "Bad news, we've had to reject your order.";
String messege = "<!DOCTYPE html>"
+ "<html>"
+ "<body>"
+ "<h4>Unfortunately, we couldn't deliver on your recent order. The following ticket{s} {have/has} been rejected:</h4>"
+ "<div name = 'tickets' style='text-indent: 20px'>"
+ "{TICKETS GO HERE}"
+ "</div>"
+ "<p>There may have been an availablilty conflict. You can try submitting a new order for{ a} similar device{s},"
+ " or for more information you can contact an administrator.</p>"
+ "</body>"
+ "<footer style='text-align: center;'><font size='1'>To change notification settings, please visit your <a href='"+profileLink+"'>profile settings page</a></font></footer>"
+ "</html>";
messege=messege.replace("{s}",tickets.length>1 ? "s" : "");
messege=messege.replace("{have/has}",tickets.length>1 ? "have" : "has");
messege=messege.replace("{ a}",tickets.length>1 ? "" : " a");
String ticketText = "";
for (Ticket t : tickets) {
ticketText+="<p>Ticket #<a href='"+ticketLink+"'>"+t.getId()+"</a> - "+t.getDeviceName()+"</p>";
}
messege=messege.replace("{TICKETS GO HERE}",ticketText);
Properties properties = System.getProperties();
properties = setProp(sender, client.getEmail());
Session session = Session.getInstance(properties, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication(sender, password);
}
});

try {
Address address = new InternetAddress(client.getEmail());
MimeMessage message = new MimeMessage(session);
message.setFrom(address);
message.addRecipient(Message.RecipientType.TO, address);
message.setSubject(subject);
message.setText(messege,"utf-8","html");
message.saveChanges();
Transport.send(message);
System.out.println("Sent message successfully....");

} catch (Exception mex) {
mex.printStackTrace();
}
}
private Properties setProp(String email, String targetEmail) {
Properties props = null;
try {
Expand Down
57 changes: 41 additions & 16 deletions src/utilities/NotificationQueue.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public class NotificationQueue extends Thread{
private String instructions="";
// this determines what information the notification queue will collect when it is finished waiting.
// >'ticketConfirmations' will cause it to query approved tickets since initialization associated with 'employee'
private int threadWaitTime = 3*60000; //3 minutes seeeeems reasonable
// This is how long a thread will stay idle before consolidating notification activity.
// The number only applies to client emails; administators may configure their own wait time.
private User employee;
public NotificationQueue(User employee, String initialize){
instructions=initialize;
Expand All @@ -41,7 +44,7 @@ public void run(){
}
System.out.println(match ? " Match!" : " No match");
if(match){
System.out.println("Redundant NotificationQueue thread will terminate");
System.out.println("Redundant NotificationQueue thread ("+threadName+") will terminate");
return; //should kill thread
}
else{
Expand All @@ -53,18 +56,32 @@ public void run(){
// Finally do the thing we came for
switch(instructions){
case "ticketConfirmations":
try {
startTicketApproveQueue(employee);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
startTicketApproveQueue(employee);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
case "ticketRejections":
try{
startTicketRejectQueue(employee);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
default:
System.out.println("NotificationQueue: Did not recognize instruction string");
Expand All @@ -80,10 +97,18 @@ private void startTicketApproveQueue(User employee) throws InterruptedException,
// Database connections are becoming a serious problem, so I'm just going to estimate that 5 seconds is more than enough
// to account for the time it took to get from the ticket generation to here.
long milliseconds = new Date().getTime()-5000;
Thread.sleep(30000);
System.out.println("NotificationQueue: sending summary email from thread "+Thread.currentThread().getName());
Ticket[] tickets = TicketQueries.getRecentApprovedTickets(employee.getID(),milliseconds);
Thread.sleep(threadWaitTime);
System.out.println("NotificationQueue: sending summary approval email from thread "+Thread.currentThread().getName());
Ticket[] tickets = TicketQueries.getRecentlyChangedTickets(employee.getID(), "Shipped", milliseconds);
Mail mail = new Mail(employee);
mail.sendTicketApproval(tickets);
}
private void startTicketRejectQueue(User employee) throws InterruptedException, ClassNotFoundException, SQLException, IOException{
long milliseconds = new Date().getTime()-5000;
Thread.sleep(threadWaitTime);
System.out.println("NotificationQueue: sending summary rejection email from thread "+Thread.currentThread().getName());
Ticket[] tickets = TicketQueries.getRecentlyChangedTickets(employee.getID(), "Rejected", milliseconds);
Mail mail = new Mail(employee);
mail.sendTicketRejection(tickets);
}
}
13 changes: 13 additions & 0 deletions src/utilities/ticketConfirmation.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- I would love to organize these templates better, but I have no idea where eclipse is putting everything when it builds the project -->
<!DOCTYPE html>
<html>
<body>
<h4>We've received your order! We'll let you know when your device{s} will ship.</h2>
<p>The following ticket{s} {was/were} generated:</p>
<div name = 'tickets' style='text-indent: 20px'>
<p>Ticket #<a href='../WebContent/html/webpages/'>12321312</a></p>
<p>Ticket #<a href='../WebContent/html/webpages/'>12321312</a></p>
</div>
</body>
<footer style='text-align: center;'><font size='2'>To change notification settings, please visit your <a href='../WebContent/html/webpages/profileSettings.jsp'>profile settings page</a></font></footer>
</html>

0 comments on commit 30999b4

Please sign in to comment.