-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.java
2623 lines (2426 loc) · 135 KB
/
Main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//Alan's final database project
//I could have coded this better, but I had to rush some of it
//due to time limitations
import java.io.File;
import java.io.IOException;
import java.util.NoSuchElementException;
import java.io.PrintWriter;
import java.util.Scanner;
import java.sql.*;
class Main{
//scroll down to the main method to see the program entry point
//escaping quotes and double quotes for SQL stuff
public static String escapeString(String strToEscape) {
strToEscape = strToEscape.replaceAll("'", """);
strToEscape = strToEscape.replaceAll("\"", """");
return strToEscape;
}
//unescapes escaped strings
//not perfect but good enough
public static String unescapeString(String strToUnescape) {
if ((strToUnescape != null) && (strToUnescape.length() != 0)) {
String unescapedString;
unescapedString = strToUnescape.replaceAll(""", "\'");
return unescapedString;
} else {
//some fields are not mandatory (lacking NOT NULL), meaning they can be blank
//but this method threw exceptions with null fields
//until I added this
//example: viewing a list of technicians, some of whom do not have specialties
//specialty is an OPTIONAL string in the Technician table
return "None";
}
}
//ticket creation method
public static void createTicket(Scanner in, Statement stmt, Technician tech) {
boolean isAdmin = tech.getIsAdmin();
System.out.println("New Ticket Creation");
//if there is an issue with how the ticket is being made,
//such as unacceptable input in the fields,
//the ticket creation will be cancelled and
//this boolean will be true and then the logged in technician
//will go back to the main menu
boolean problem = false;
//getting employee ID and verifying that the input is an integer
//I do a lot of input validation before putting anything into the database
int empID = -1;
System.out.print("Enter employee ID of person requesting support: ");
String empIDString = in.nextLine();
try {
empID = Integer.parseInt(empIDString);
} catch (NumberFormatException ex) {
System.out.println("Error: empID must be a number");
problem = true;
}
//probably should have just used a loop and break;
//instead of this boolean switch for continuing with the ticket creation
//make sure employee with that employee ID actually exists
if (!problem) {
//employee ID 1 is reserved for a "deleted" placeholder used by tickets
if (empID == 1) {
System.out.println("Error: invalid employee ID.");
problem = true;
}
String empIdExistsQuery = "SELECT COUNT(*) AS empIdExists FROM Employee WHERE employeeID = " + empID;
try {
ResultSet empIdExistsRS = stmt.executeQuery(empIdExistsQuery);
int empIdExists = 0;
if (empIdExistsRS.next()) {
empIdExists = empIdExistsRS.getInt("empIdExists");
}
if (!(empIdExists == 1)) {
System.out.println("Error: employee with specified ID does not exist");
problem = true;
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
//if employee is fired but their record still exists, they are not allowed to get support
if (!problem) {
//check if employee is fired, with the currentlyHired column in the Employee table
//fired technicians cannot log in, and fired employees cannot make tickets
String empIsNotFiredQuery = "SELECT currentlyHired FROM Employee WHERE employeeID = " + empID;
try {
ResultSet empIsNotFiredRS = stmt.executeQuery(empIsNotFiredQuery);
int empHiredStatusInt = 0;
if (empIsNotFiredRS.next()) {
empHiredStatusInt = empIsNotFiredRS.getInt("currentlyHired");
}
if (empHiredStatusInt == 0) {
System.out.println("WARNING: This employee has been fired. You are not allowed to help them with tech issues.");
System.out.println("Ticket cannot be created.");
problem = true;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//get the title of the ticket
//kind of like the title vs. body in an email
String titleString = "not set up yet"; //placeholder value just so it's not null
if (!problem) {
System.out.print("Enter the title of the issue (max 50 characters): ");
titleString = in.nextLine();
if (titleString.length() > 50) {
System.out.println("Error: title cannot be longer than 50 characters.");
problem = true;
} else if (titleString.length() == 0) {
System.out.println("Error: title cannot be blank.");
problem = true;
}
}
//getting the description for the ticket
//description is longer text to describe the in-depth details of the tech issue
String descriptionString = "not set up yet";
if (!problem) {
System.out.print("Enter the description of the issue (max 1000 chars but no linebreaks): ");
descriptionString = in.nextLine();
if (descriptionString.length() > 1000) {
System.out.println("Error: description cannot be longer than 1000 characters.");
problem = true;
} else if (descriptionString.length() == 0) {
System.out.println("Error: description cannot be blank.");
problem = true;
}
}
//difficulty number can be used for sorting by difficulty in ascending order
//can be useful for novice IT interns at a company who only want to look at
//easy tickets
//technicians can have experience levels of 1, 2, or 3 (novice, intermediate, expert)
//tickets can have difficulty levels of 1, 2, or 3 (easy, medium, hard)
int difficulty = -1;
if (!problem) {
System.out.print("Enter estimated difficulty number (1 = easy, 2 = medium, 3 = hard): ");
String difficultyString = in.nextLine();
switch (difficultyString) {
case "1":
//easy
difficulty = 1;
break;
case "2":
//medium
difficulty = 2;
break;
case "3":
//medium
difficulty = 3;
break;
default:
System.out.println("Error: invalid choice. Difficulty must be 1, 2, or 3.");
problem = true;
}
}
int openStatus = -1; //I use -1 when I plan on changing it later, and -1 means it hasn't been set up correctly yet
int assignedID = -1; //nobody can have an ID of -1, this means unassigned
if (!problem) {
openStatus = 1; //an unfinished ticket is an open ticket, closed means done
//1 = true, 0 = false for the mysql tinyint(1)
System.out.println("Leave the ticket unassigned for now?");
System.out.println("1. Leave ticket unassigned, figure out who is suitable for it later.");
System.out.println("2. Assign the ticket.");
System.out.print("Choice: ");
String assignmentChoice = in.nextLine();
if (assignmentChoice.equals("2")) {
//only admins can assign work to other employees
//a technician can only assign either nobody or themselves
//delete this next line, only using it for dev purposes
//isAdmin = true;
//delete or comment out the above line!!!
if (isAdmin) {
System.out.println("Do you want to assign yourself to the ticket or someone else?");
System.out.println("1. Myself");
System.out.println("2. Some other technician");
System.out.print("Choice: ");
String adminAssignChoice = in.nextLine();
if (adminAssignChoice.equals("1")) {
System.out.println("You have been assigned to this ticket.");
assignedID = tech.getTechnicianID();
} else if (adminAssignChoice.equals("2")) {
System.out.print("Enter the Technician ID of the technician to assign the ticket to: ");
//checking if the technicianID is an integer
int adminTechIdChoice = -1;
try {
adminTechIdChoice = Integer.parseInt(in.nextLine());
} catch (NumberFormatException e) {
System.out.println("Error: technician ID must be a number.");
problem = true;
}
//tech ID 1 is reserved for a "deleted" placeholder
if (adminTechIdChoice == 1) {
System.out.println("Error: invalid technician ID.");
problem = true;
}
//check if there is a technician with that ID number
String verifyTechIdQuery = "SELECT COUNT(technicianID) as adminTechIdVerify FROM Technician WHERE technicianID = " + adminTechIdChoice;
try {
ResultSet verifyTechIdRS = stmt.executeQuery(verifyTechIdQuery);
int verifyTechIdResults = -1;
if (verifyTechIdRS.next()) {
verifyTechIdResults = verifyTechIdRS.getInt("adminTechIdVerify");
if (verifyTechIdResults == 1) {
//there is a technician with that ID
assignedID = verifyTechIdResults;
} else {
System.out.println("Error: there is no technician with that ID number.");
problem = true;
}
} else {
System.out.println("Error with SQL query.");
problem = true;
}
} catch (SQLException ex) {
ex.printStackTrace();
}
} else {
System.out.println("Error: invalid choice.");
problem = true;
}
} else {
//not admin, can only assign tickets to themselves
System.out.println("You have been assigned to this ticket.");
//assigning yourself to the ticket
assignedID = tech.getTechnicianID();
}
} else if (assignmentChoice.equals("1")) {
System.out.println("The ticket is unassigned for now. Someone can take it later.");
} else {
System.out.println("Error: invalid choice.");
problem = true;
}
}
//assigning a standard procedure to it
int standardProcedureChoice = -1;
if (!problem) {
System.out.print("Would you like to assign a standard procedure to this ticket? y/n: ");
String procedureChoice = in.nextLine();
if (procedureChoice.equals("y") || procedureChoice.equals("yes")) {
//user wants to assign a procedure, but it's useful to see the procedure names and numbers
//instead of memorizing them
System.out.println("Enter a procedure # to assign or type c to cancel adding one:");
System.out.println("Entering c will only cancel adding a procedure, not cancel making the ticket.");
String viewProceduresQuery = "SELECT procedureID, name FROM StandardProcedure WHERE procedureID != 1 ORDER BY procedureID ASC";
try {
ResultSet listOfProcedures = stmt.executeQuery(viewProceduresQuery);
//multiple results in the result set
while (listOfProcedures.next()) {
//showing list of procedure names along with their numbers
int procedureNumber = listOfProcedures.getInt("procedureID");
String procedureName = listOfProcedures.getString("name");
System.out.println(procedureNumber + ". " + procedureName);
}
//getting procedure choice from technician
System.out.print("Choice (enter a number or c): ");
String procedureNumberChoice = in.nextLine();
//c means cancel
if (procedureNumberChoice.equals("c")) {
System.out.println("No procedure will be added to this ticket.");
} else {
try {
standardProcedureChoice = Integer.parseInt(procedureNumberChoice);
if (standardProcedureChoice == 1) {
System.out.println("Error: invalid procedure choice. No procedure will be added but the ticket will still be made.");
} else {
//making sure there is actually a procedure with that number in the procedure table
String verifyProcedureIdQuery = "SELECT COUNT(procedureID) AS procedureIdExists FROM StandardProcedure WHERE procedureID = " + standardProcedureChoice;
ResultSet procedureIdVerifyRS = stmt.executeQuery(verifyProcedureIdQuery);
if (procedureIdVerifyRS.next()) {
int procedureIdExists = procedureIdVerifyRS.getInt("procedureIdExists");
if (procedureIdExists == 1) {
//procedure has been verified and set
standardProcedureChoice = standardProcedureChoice;
} else {
System.out.println("Error: no such procedure. Ticket will still be made, but with no procedure associated with it.");
}
} else {
System.out.println("Error: SQL query issue");
problem = true;
}
}
} catch (NumberFormatException num) {
System.out.println("Error: invalid procedure choice.");
System.out.println("No procedure will be added now, but you can edit the ticket later if you want.");
}
}
} catch (SQLException e) {
e.printStackTrace();
}
} else if (procedureChoice.equals("n") || procedureChoice.equals("no")) {
System.out.println("There will be no standard procedure associated with this ticket.");
} else {
System.out.println("Error: invalid choice");
problem = true;
}
}
//creating a ticket with the values from the user
//huge query because tickets have so many columns
if (!problem) {
//this code is probably vulnerable to SQL injection
//but this is just a college project and not something that would be used in a production system
//but in a job environment, I would write extra code that would make sure the values aren't doing SQL injection
//need to escape the title and description fields
//I tried it with an example ticket that said "computer won't boot"
//and the apostrophe messed it up
titleString = titleString.replaceAll("'", """);
titleString = titleString.replaceAll("\"", """");
descriptionString = descriptionString.replaceAll("\'", """);
descriptionString = descriptionString.replaceAll("\"", """");
String ticketCreationQuery = "INSERT INTO Ticket (dateCreated, title, description, difficulty, openStatus,";
//notice that there is no ticketID entered here because I have it auto increment so it will be made automatically
ticketCreationQuery += "solutionSummary, assignedTechnicianID, assignedEmployeeID, assignedProcedureID) VALUES ";
ticketCreationQuery += "(CURRENT_TIMESTAMP(), '" + titleString + "', '" + descriptionString + "', " + difficulty + ", ";
//solutionSummary is NULL because a new ticket hasn't been finished and thus cannot have a solution written for it yet
ticketCreationQuery += openStatus + ", NULL, ";
//checking if no technician is assigned to the ticket
if (assignedID == -1) {
ticketCreationQuery += "NULL, ";
} else {
ticketCreationQuery += assignedID + ", ";
}
//all tickets have employees associated with them
ticketCreationQuery += empID + ", ";
//not all tickets have a procedure assigned to them
if (standardProcedureChoice == -1) {
ticketCreationQuery += "NULL)";
} else {
ticketCreationQuery += standardProcedureChoice + ")";
}
//System.out.println("ticketCreationQuery: ");
//System.out.println(ticketCreationQuery);
try {
//finally making the ticket
//not a SELECT so I don't need a ResultSet
stmt.executeUpdate(ticketCreationQuery);
} catch (SQLException s) {
System.err.println("Error with SQL query");
s.printStackTrace();
}
System.out.println("Ticket has been created.");
}
}
//helper method for viewTickets so I don't have to be repetitive
//used for many specific queries, but they all have some things in common
//but with slightly different queries
public static void generalTicketLister(String query, Statement stmt) {
System.out.println("Priority should go to the oldest tickets because those people have waited the longest.");
System.out.println(String.format("%-10s%-22s%-12s%-55s", "TicketID", "Date", "Difficulty", "Title"));
boolean atLeastOneResult = false;
try {
//print results of each ticket -- just basic stuff, not every column
ResultSet myOpenTicketsRS = stmt.executeQuery(query);
while (myOpenTicketsRS.next()) {
int myOpenTicketID = myOpenTicketsRS.getInt("ticketID");
String myOpenTicketDate = myOpenTicketsRS.getString("dateCreated");
int myOpenTicketDifficulty = myOpenTicketsRS.getInt("difficulty");
String myOpenTicketTitle = myOpenTicketsRS.getString("title");
//convert difficulty integers to strings
String myOpenTicketDifficultyString = "";
switch (myOpenTicketDifficulty) {
case 1:
myOpenTicketDifficultyString = "Easy";
atLeastOneResult = true;
break;
case 2:
myOpenTicketDifficultyString = "Medium";
atLeastOneResult = true;
break;
case 3:
myOpenTicketDifficultyString = "Hard";
atLeastOneResult = true;
break;
default:
myOpenTicketDifficultyString = "error";
break;
}
//unescaping the escaped stuff from the database
myOpenTicketTitle = myOpenTicketTitle.replaceAll(""", "'");
System.out.println(String.format("%-10d%-22s%-12s%-55s", myOpenTicketID, myOpenTicketDate, myOpenTicketDifficultyString, myOpenTicketTitle));
}
} catch (SQLException e) {
e.printStackTrace();
}
if (atLeastOneResult == false) {
System.out.println("No results.");
}
}
//ticket viewing
public static void viewTickets(Scanner in, Statement stmt, Technician tech) {
System.out.print("Choice: ");
String viewTicketMenuChoice = in.nextLine();
switch (viewTicketMenuChoice) {
case "1":
//list all tickets you're assigned to
//just basic info, not the description and other more detailed info
//to see detailed info, use option 6
//either basic info about a list of tickets, or detailed info about just one ticket
//too much stuff per ticket to show it all at once in a list
System.out.println("Your open tickets:");
String myOpenTicketsQuery = "SELECT ticketID, dateCreated, difficulty, title FROM AllOpenTickets WHERE assignedTechnicianID = " + tech.getTechnicianID();
generalTicketLister(myOpenTicketsQuery, stmt);
break;
case "2":
System.out.println("All tickets you are assigned to:");
String allMyTicketsQuery = "SELECT ticketID, dateCreated, difficulty, title FROM AllTickets WHERE assignedTechnicianID = " + tech.getTechnicianID();
generalTicketLister(allMyTicketsQuery, stmt);
break;
case "3":
System.out.println("All unassigned open tickets:");
String allUnassignedOpenTicketsQuery = "SELECT ticketID, dateCreated, difficulty, title FROM AllOpenTickets WHERE assignedTechnicianID IS NULL";
generalTicketLister(allUnassignedOpenTicketsQuery, stmt);
break;
case "4":
System.out.println("All open tickets (including yours, unassigned, and ones assigned to other people):");
String allOpenTicketsQuery = "SELECT ticketID, dateCreated, difficulty, title FROM AllOpenTickets";
generalTicketLister(allOpenTicketsQuery, stmt);
break;
case "5":
System.out.println("All tickets, from everyone, from all time, including closed ones:");
String allTicketsQuery = "SELECT ticketID, dateCreated, difficulty, title FROM AllTickets";
generalTicketLister(allTicketsQuery, stmt);
break;
case "6":
//view detailed info about a single ticket
//the other options are lists with only basic info about them
System.out.println("Read detailed info about a specific ticket by ID");
System.out.println("If you don't know the ID of the ticket you want to look up, use the other menu options first.");
System.out.print("Enter ticketID number: ");
int ticketChoice = -1;
boolean searchIntProblem = false;
try {
ticketChoice = Integer.parseInt(in.nextLine());
} catch (NumberFormatException e) {
System.out.println("Error: ticketID must be a number.");
searchIntProblem = true;
}
//now need to make sure there is actually a ticket with that ID number
String ticketSearchVerifyQuery = "SELECT COUNT(ticketID) AS searchedTicketExists FROM Ticket WHERE ticketID = " + ticketChoice;
if (searchIntProblem == false) {
try {
ResultSet searchedTicketExists = stmt.executeQuery(ticketSearchVerifyQuery);
if (searchedTicketExists.next()) {
int searchTicketInt = searchedTicketExists.getInt("searchedTicketExists");
if (searchTicketInt == 1) {
//printing detailed ticket info
System.out.println("TicketID: " + ticketChoice);
String detailedTicketInfoQuery = "SELECT ticketID, dateCreated, title, description, difficulty, ";
detailedTicketInfoQuery += "openStatus, solutionSummary, assignedEmployeeID, assignedTechnicianID, assignedProcedureID FROM Ticket WHERE ticketID = " + ticketChoice;
try {
ResultSet detailedTicketInfoRS = stmt.executeQuery(detailedTicketInfoQuery);
if (detailedTicketInfoRS.next()) {
String detailedDate = detailedTicketInfoRS.getString("dateCreated");
System.out.println("Date created: " + detailedDate);
//joining Employee and Ticket tables to get the name of the employee associated with the ticket
String getEmployeeNameQuery = "SELECT e.firstName, e.lastName, e.employeeID, e.phoneNumber, e.emailAddress, e.officeLocation FROM Employee e, Ticket t WHERE e.employeeID = t.assignedEmployeeID AND t.ticketID = " + ticketChoice;
ResultSet getEmployeeNameRS = stmt.executeQuery(getEmployeeNameQuery);
String detailedTicketEmployee = "";
if (getEmployeeNameRS.next()) {
detailedTicketEmployee = getEmployeeNameRS.getString("e.firstName") + " ";
detailedTicketEmployee += getEmployeeNameRS.getString("e.lastName") + "\nEmployeeID ";
detailedTicketEmployee += getEmployeeNameRS.getInt("e.employeeID") + ", ";
detailedTicketEmployee += getEmployeeNameRS.getString("e.phoneNumber") + ", ";
detailedTicketEmployee += getEmployeeNameRS.getString("e.emailAddress") + ", Room #";
detailedTicketEmployee += getEmployeeNameRS.getInt("e.officeLocation");
}
detailedTicketEmployee = detailedTicketEmployee.replaceAll(""", "'");
System.out.println("Requested by: " + detailedTicketEmployee);
ResultSet detailedTicketInfoRS2 = stmt.executeQuery(detailedTicketInfoQuery);
if (detailedTicketInfoRS2.next()) {
//I'm doing multiple queries because making a separate query for the foreign key stuff
//closes the first thing and messes it up
//apparently only one executeQuery thing at a time, or at least that's what it seems to me
String detailedDifficulty = detailedTicketInfoRS2.getString("difficulty");
System.out.println("Difficulty: " + detailedDifficulty);
int detailedOpenStatus = detailedTicketInfoRS2.getInt("openStatus");
String detailedOpenString = "Closed";
if (detailedOpenStatus == 1) {
detailedOpenString = "Open";
}
System.out.println("Status: " + detailedOpenString);
//check if there is even a technician assigned to the ticket
//because it could be null
String checkIfTechIsAssigned = "SELECT COUNT(*) AS detailedTicketTechExists FROM Technician tech, Ticket tick ";
checkIfTechIsAssigned += "WHERE tech.technicianID = tick.assignedTechnicianID AND tick.ticketID = " + ticketChoice;
int technicianAssignedToTicket = -1;
ResultSet checkIfTechExistsDetailedRS = stmt.executeQuery(checkIfTechIsAssigned);
String detailedTechnicianString = "None";
if (checkIfTechExistsDetailedRS.next()) {
int techExistsIntDetailedTicket = checkIfTechExistsDetailedRS.getInt("detailedTicketTechExists");
if (techExistsIntDetailedTicket == 1) {
//there is a technician associated with this ticket
String detailedTechnicianQuery = "SELECT tech.firstName, tech.lastName, tech.technicianID, tech.phoneNumber, tech.emailAddress, ";
detailedTechnicianQuery += "tech.officeLocation FROM Ticket tick, Technician tech ";
detailedTechnicianQuery += "WHERE tech.technicianID = tick.assignedTechnicianID AND tick.ticketID = " + ticketChoice;
ResultSet detailedTechnicianRS3 = stmt.executeQuery(detailedTechnicianQuery);
if (detailedTechnicianRS3.next()) {
//printing technician info
detailedTechnicianString = "";
detailedTechnicianString += detailedTechnicianRS3.getString("tech.firstName") + " ";
detailedTechnicianString += detailedTechnicianRS3.getString("tech.lastName") + "\nTechnicianID ";
detailedTechnicianString += detailedTechnicianRS3.getString("tech.technicianID") + ", ";
detailedTechnicianString += detailedTechnicianRS3.getString("tech.phoneNumber") + ", ";
detailedTechnicianString += detailedTechnicianRS3.getString("tech.emailAddress") + ", Room #";
detailedTechnicianString += detailedTechnicianRS3.getString("tech.officeLocation");
}
}
}
System.out.println("Technician assigned to ticket: " + detailedTechnicianString);
String detailTickCheckIfSPassigned = "SELECT COUNT(*) AS detailedProcExists FROM StandardProcedure sp, Ticket t WHERE ";
detailTickCheckIfSPassigned += "sp.procedureID = t.assignedProcedureID AND t.ticketID = " + ticketChoice;
ResultSet detailedTicketHasProcRS = stmt.executeQuery(detailTickCheckIfSPassigned);
String detailedProcedureString = "None";
if (detailedTicketHasProcRS.next()) {
int detailedProcInt = detailedTicketHasProcRS.getInt("detailedProcExists");
if (detailedProcInt == 1) {
//this ticket has a standard procedure associated with it
String detailedTicketProcedureQuery = "SELECT sp.procedureID, sp.name, sp.instructions FROM Ticket t, StandardProcedure sp ";
detailedTicketProcedureQuery += "WHERE sp.procedureID = t.assignedProcedureID AND t.ticketID = " + ticketChoice;
ResultSet detailedProcInfoRS = stmt.executeQuery(detailedTicketProcedureQuery);
if (detailedProcInfoRS.next()) {
//setting the var to the procedure info
detailedProcedureString = "";
detailedProcedureString += detailedProcInfoRS.getString("sp.name") + " (procedureID ";
detailedProcedureString += detailedProcInfoRS.getInt("sp.procedureID") + ")\n";
detailedProcedureString += "Procedure instructions: " + detailedProcInfoRS.getString("sp.instructions");
detailedProcedureString = detailedProcedureString.replaceAll(""", "'");
}
}
}
System.out.println("Standard procedure: " + detailedProcedureString);
String detailedDescription = "";
String detailedTitleAndDescription = "SELECT title, description, solutionSummary FROM Ticket ";
detailedTitleAndDescription += "WHERE ticketID = " + ticketChoice;
ResultSet detailedTitleDescriptRS = stmt.executeQuery(detailedTitleAndDescription);
if (detailedTitleDescriptRS.next()) {
detailedDescription = detailedTitleDescriptRS.getString("description");
detailedDescription = detailedDescription.replaceAll(""", "'");
String detailedTicketTitle = detailedTitleDescriptRS.getString("title");
detailedTicketTitle = detailedTicketTitle.replaceAll(""", "'");
System.out.println("Ticket title: " + detailedTicketTitle);
System.out.println("Ticket description: " + detailedDescription);
String detailTicketSolutionSummary = detailedTitleDescriptRS.getString("solutionSummary");
String detailedSolutionSummaryString = "None";
if (detailTicketSolutionSummary != null) {
detailedSolutionSummaryString = "";
detailedSolutionSummaryString += detailedTitleDescriptRS.getString("solutionSummary");
detailedSolutionSummaryString = detailedSolutionSummaryString.replaceAll(""", "'");
System.out.println("Solution summary: " + detailedSolutionSummaryString);
}
}
/*
String detailedSummary = detailedTicketInfoRS2.getString("solutionSummary");
if (detailedSummary != null) {
detailedSummary = detailedSummary.replaceAll(""", "'");
}
System.out.println("Solution summary: " + detailedSummary);*/
}
}
} catch (SQLException e) {
e.printStackTrace();
}
} else {
System.out.println("Error: no such ticket with that ID.");
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
break;
case "7":
//search by text (for title or description) or by difficulty level
System.out.println("Search tickets by text or difficulty level");
System.out.println("What do you want to search by?");
System.out.println("1. Text");
System.out.println("2. Difficulty level");
System.out.print("Choice: ");
String typeOfSearch = in.nextLine();
switch (typeOfSearch) {
case "1":
//text search for tickets
System.out.println("Which tickets do you want to search by text?");
System.out.println("1. My open tickets");
System.out.println("2. Unassigned open tickets");
System.out.println("3. All tickets");
System.out.print("Choice: ");
String typeOfTextSearch = in.nextLine();
switch (typeOfTextSearch) {
case "1":
System.out.print("Enter search term: ");
String textToSearch = in.nextLine();
textToSearch = textToSearch.replaceAll("'", """);
textToSearch = textToSearch.replaceAll("\"", """");
String searchMyOpenTicketsTextQuery = "SELECT ticketID, dateCreated, title, difficulty FROM TicketTextSearch WHERE assignedTechnicianID = ";
searchMyOpenTicketsTextQuery += tech.getTechnicianID() + " AND openStatus = 1 AND (title LIKE '%" + textToSearch;
searchMyOpenTicketsTextQuery += "%' OR description LIKE '%" + textToSearch + "%')";
generalTicketLister(searchMyOpenTicketsTextQuery, stmt);
break;
case "2":
System.out.print("Enter search term: ");
String textToSearch2 = in.nextLine();
//I wrote this repetitive manual escaping/unescaping stuff
//before I made the escapeString() and unescapeString() methods
//but I only used the new method on new parts of the program
//because I don't feel like refactoring everything
textToSearch2 = textToSearch2.replaceAll("'", """);
textToSearch2 = textToSearch2.replaceAll("\"", """");
String searchUnassignedOpenTicketsTextQuery = "SELECT ticketID, dateCreated, title, difficulty FROM TicketTextSearch WHERE assignedTechnicianID IS ";
searchUnassignedOpenTicketsTextQuery += "NULL AND openStatus = 1 AND (title LIKE '%" + textToSearch2;
searchUnassignedOpenTicketsTextQuery += "%' OR description LIKE '%" + textToSearch2 + "%')";
generalTicketLister(searchUnassignedOpenTicketsTextQuery, stmt);
break;
case "3":
System.out.print("Enter search term: ");
String textToSearch3 = in.nextLine();
textToSearch3 = textToSearch3.replaceAll("'", """);
textToSearch3 = textToSearch3.replaceAll("\"", """");
String searchAllTicketsTextQuery = "SELECT ticketID, dateCreated, title, difficulty FROM TicketTextSearch WHERE ";
searchAllTicketsTextQuery += "title LIKE '%" + textToSearch3;
searchAllTicketsTextQuery += "%' OR description LIKE '%" + textToSearch3 + "%'";
generalTicketLister(searchAllTicketsTextQuery, stmt);
break;
default:
System.out.println("Invalid menu choice.");
break;
}
break;
case "2":
//search tickets by difficulty level
//sub-menu with more options
System.out.println("What difficulty do you want to search for?");
System.out.println("1. Open and unassigned tickets that are suitable for my skill level");
System.out.println("2. Open and unassigned tickets that are a specific difficulty level");
System.out.println("3. All tickets that are a certain difficulty level");
System.out.print("Choice: ");
String difficultyChoice = in.nextLine();
switch (difficultyChoice) {
case "1":
String openUnassignedMyDifficultyQuery = "SELECT ticketID, dateCreated, difficulty, title FROM AllOpenTickets WHERE difficulty = ";
openUnassignedMyDifficultyQuery += tech.getExperienceLevel() + " AND assignedTechnicianID IS NULL";
generalTicketLister(openUnassignedMyDifficultyQuery, stmt);
break;
case "2":
System.out.print("Enter difficulty level to search for (1, 2, or 3): ");
String specificDifficultyChoice = in.nextLine();
switch (specificDifficultyChoice) {
case "1":
String searchLevel1Difficulty = "SELECT ticketID, dateCreated, difficulty, title FROM AllOpenTickets WHERE difficulty = 1";
generalTicketLister(searchLevel1Difficulty, stmt);
break;
case "2":
String searchLevel2Difficulty = "SELECT ticketID, dateCreated, difficulty, title FROM AllOpenTickets WHERE difficulty = 2";
generalTicketLister(searchLevel2Difficulty, stmt);
break;
case "3":
String searchLevel3Difficulty = "SELECT ticketID, dateCreated, difficulty, title FROM AllOpenTickets WHERE difficulty = 3";
generalTicketLister(searchLevel3Difficulty, stmt);
break;
default:
System.out.println("Invalid menu choice.");
break;
}
break;
case "3":
System.out.print("Enter difficulty level to search for (1, 2, or 3): ");
String allSpecificDifficultyChoice = in.nextLine();
switch (allSpecificDifficultyChoice) {
case "1":
String searchLevel1Difficulty = "SELECT ticketID, dateCreated, difficulty, title FROM AllTickets WHERE difficulty = 1";
generalTicketLister(searchLevel1Difficulty, stmt);
break;
case "2":
String searchLevel2Difficulty = "SELECT ticketID, dateCreated, difficulty, title FROM AllTickets WHERE difficulty = 2";
generalTicketLister(searchLevel2Difficulty, stmt);
break;
case "3":
String searchLevel3Difficulty = "SELECT ticketID, dateCreated, difficulty, title FROM AllTickets WHERE difficulty = 3";
generalTicketLister(searchLevel3Difficulty, stmt);
break;
default:
System.out.println("Invalid menu choice.");
break;
}
break;
default:
System.out.println("Invalid menu choice.");
break;
}
break;
default:
System.out.println("Invalid menu choice.");
break;
}
break;
case "8":
System.out.println("Returning to main menu.");
break;
case "q":
case "Q":
case "quit":
System.out.println("Goodbye");
System.exit(0);
default:
System.out.println("Invalid menu choice.");
break;
}
}
//view procedures method
public static void viewProcedures(Scanner in, Statement stmt, Technician tech) {
System.out.print("Choice: ");
String procViewingMenuChoice = in.nextLine();
switch (procViewingMenuChoice) {
case "1":
System.out.println("View list of procedures");
//procedureID 1 is a special reserved "deleted" placeholder
//a ticket can exist even if you delete the procedure, employee, or technician associated with it
String viewAllProceduresQuery = "SELECT * FROM ListOfProcedures WHERE procedureID <> 1";
try {
System.out.println(String.format("%-15s%-32s", "ProcedureID", "Procedure Name"));
ResultSet viewAllProcRS = stmt.executeQuery(viewAllProceduresQuery);
while (viewAllProcRS.next()) {
int viewProcID = viewAllProcRS.getInt("procedureID");
String viewProcName = viewAllProcRS.getString("name");
viewProcName = viewProcName.replaceAll(""", "'");
System.out.println(String.format("%-15s%-32s", viewProcID, viewProcName));
}
} catch (SQLException e) {
e.printStackTrace();
}
break;
case "2":
System.out.println("View detailed procedure info for a single procedure (by ID number)");
System.out.print("Enter procedure ID to look up: ");
String detailedProcedureChoice = in.nextLine();
//validate input
try {
int procedureToLookUp = Integer.parseInt(detailedProcedureChoice);
//edge case "deleted" placeholder for ID 1
if (procedureToLookUp == 1) {
System.out.println("Error: invalid procedure ID.");
} else {
try {
//now need to check if there is such a procedure in the database
String checkIfProcNumExists = "SELECT COUNT(*) AS procNumExists FROM ListOfProcedures WHERE ";
checkIfProcNumExists += "procedureID = " + procedureToLookUp;
ResultSet ifProcNumExistsRS = stmt.executeQuery(checkIfProcNumExists);
if (ifProcNumExistsRS.next()) {
int procNumExistsInt = ifProcNumExistsRS.getInt("procNumExists");
if (procNumExistsInt == 1) {
//procedure with that ID exists
//printing out procedure info
String detailedProcedureQuery = "SELECT * FROM StandardProcedure WHERE procedureID = " + procedureToLookUp;
ResultSet detailedProcedureRS = stmt.executeQuery(detailedProcedureQuery);
if (detailedProcedureRS.next()) {
String detailedProcedureName = detailedProcedureRS.getString("name");
detailedProcedureName = detailedProcedureName.replaceAll(""", "'");
String detailedProcedureInstructions = detailedProcedureRS.getString("instructions");
detailedProcedureInstructions = detailedProcedureInstructions.replaceAll(""", "'");
System.out.println("Procedure Name: " + detailedProcedureName);
System.out.println("Procedure ID: " + procedureToLookUp);
System.out.println("Procedure instructions: " + detailedProcedureInstructions);
}
} else {
System.out.println("Error: no procedure has that ID.");
}
}
} catch (SQLException s) {
s.printStackTrace();
}
}
} catch (NumberFormatException e) {
System.out.println("Error: procedure ID must be a number.");
}
break;
case "3":
//search for procedures with user input
System.out.println("Search procedures by text");
System.out.print("Enter a search term: ");
String procSearchText = in.nextLine();
//new escape method so I don't have to keep on repetitively doing manual escapes/unescapes
procSearchText = escapeString(procSearchText);
//search through titles and instructions for search term
String procTextSearchQuery = "SELECT procedureID, name, instructions FROM StandardProcedure WHERE name LIKE '%";
procTextSearchQuery += procSearchText + "%' OR instructions LIKE '%" + procSearchText + "%'";
//System.out.println(procTextSearchQuery);
System.out.println("Procedure ID, name, and instructions");
System.out.println("Search results:");
boolean atLeastOneProcTextSearchResult = false;
try {
ResultSet procTextSearchRS = stmt.executeQuery(procTextSearchQuery);
//loop through all results, could be zero to many
while (procTextSearchRS.next()) {
int procIdFromProcSearch = procTextSearchRS.getInt("procedureID");
String procIdNameSearch = unescapeString(procTextSearchRS.getString("name"));
String procInstructionsSearch = unescapeString(procTextSearchRS.getString("instructions"));
System.out.println(String.format("Procedure Name: %s, Procedure ID: %d", procIdNameSearch, procIdFromProcSearch));
System.out.println("Instructions: " + procInstructionsSearch);
System.out.println("----------");
atLeastOneProcTextSearchResult = true;
}
if (!atLeastOneProcTextSearchResult) {
System.out.println("No results.");
}
} catch (SQLException s) {
s.printStackTrace();
}
break;
case "4":
System.out.println("Returning to main menu.");
break;
case "q":
case "Q":
case "quit":
System.out.println("Goodbye.");
System.exit(0);
default:
System.out.println("Invalid menu choice.");
break;
}
}
//edit your own technician account info
//admins can do some things that regular technicians can't
public static void editSelfInfo(Scanner in, Statement stmt, Technician tech) {
System.out.println("Please note that apostrophes and quotes will be escaped, making them take up more characters.");
int idToUpdate = -1;
//admin gets to choose which technician they want to edit
//reg tech can only edit their own technician account
if (tech.getIsAdmin()) {
System.out.print("Enter the technicianID of the technician you want to edit: ");
try {
idToUpdate = Integer.parseInt(in.nextLine());
} catch (NumberFormatException e) {
System.out.println("Error: technicianID must be a number.");
e.printStackTrace();
return;
}
} else {
idToUpdate = tech.getTechnicianID();
}
System.out.print("Column to edit choice (from numeric list above): ");
String editSelfMainChoice = in.nextLine();
switch (editSelfMainChoice) {
case "1":
//I realize that these cases are repetitive, and I would have refactored stuff
//and turned this stuff into a more generalized method
//but I ran out of time
System.out.print("Enter a new first name (max 15 chars): ");
String newFirstNameChoice = in.nextLine();
newFirstNameChoice = escapeString(newFirstNameChoice);
if ((newFirstNameChoice.length() != 0) && (newFirstNameChoice.length() <= 15)) {
String newFirstNameUpdate = "UPDATE Technician SET firstName = '" + newFirstNameChoice;
newFirstNameUpdate += "' WHERE technicianID = " + idToUpdate;
try {
stmt.executeUpdate(newFirstNameUpdate);
} catch (SQLException e) {
e.printStackTrace();
}
} else {
System.out.println("Error: input length issue.");
}
break;
case "2":
//I realized how repetitive this is and that I should put it all in a function
//after I wrote a lot of it
System.out.print("Enter a new last name (max 15 chars): ");
String newLastNameChoice = in.nextLine();
newLastNameChoice = escapeString(newLastNameChoice);
if ((newLastNameChoice.length() != 0) && (newLastNameChoice.length() <= 15)) {
String newLastNameUpdate = "UPDATE Technician SET lastName = '" + newLastNameChoice;
newLastNameUpdate += "' WHERE technicianID = " + idToUpdate;
try {
stmt.executeUpdate(newLastNameUpdate);
} catch (SQLException e) {
e.printStackTrace();
}
} else {
System.out.println("Error: input length issue.");
}
break;
case "3":
//I would have used regular expressions for pattern matching,
//but I ran out of time
//so I had to cut out some of the extra features
//but for a real-world ticketing system, you'd need to verify
//that the submitted phone number is actually a phone number
System.out.println("Phone number format: 123-456-7890");
System.out.print("Enter a phone number (max 12 chars): ");
String newPhoneNumberChoice = in.nextLine();
newPhoneNumberChoice = escapeString(newPhoneNumberChoice);
if ((newPhoneNumberChoice.length() != 0) && (newPhoneNumberChoice.length() <= 12)) {
String newPhoneNumberUpdate = "UPDATE Technician SET phoneNumber = '" + newPhoneNumberChoice;
newPhoneNumberUpdate += "' WHERE technicianID = " + idToUpdate;
try {
stmt.executeUpdate(newPhoneNumberUpdate);
} catch (SQLException e) {
e.printStackTrace();
}
} else {
System.out.println("Error: input length issue.");
}
break;
case "4":
System.out.print("Enter a email address (max 30 chars): ");
String newEmailAddressChoice = in.nextLine();
newEmailAddressChoice = escapeString(newEmailAddressChoice);
if ((newEmailAddressChoice.length() != 0) && (newEmailAddressChoice.length() <= 30)) {
String newEmailAddressUpdate = "UPDATE Technician SET emailAddress = '" + newEmailAddressChoice;
newEmailAddressUpdate += "' WHERE technicianID = " + idToUpdate;
try {
stmt.executeUpdate(newEmailAddressUpdate);
} catch (SQLException e) {
e.printStackTrace();
}
} else {