initial commit
[CPE_learningsite] / CPE / CPE.App / CPE.App.Web / Controllers / IndexController.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Configuration;
4 using System.Linq;
5 using System.Net;
6 using System.Net.Mail;
7 using System.Text.RegularExpressions;
8 using System.Web;
9 using System.Web.Mvc;
10 using System.Xml;
11 using CPE.App.Web.Code;
12 using CPE.App.Web.Connect;
13 using CPE.App.Web.Helpers;
14 using CPE.App.Web.Models;
15
16 namespace CPE.App.Web.Controllers {
17     public class IndexController : BaseController {
18         public enum MeetingType {
19             Adobe,
20             Elucidat
21         }
22
23         private bool IsLocal() {
24             var address = Request.UserHostAddress;
25             if (address.StartsWith("192.") || address.StartsWith("10.211") || address == "::1")
26                 return true;
27             return false;
28         }
29
30         // GET: Index
31         [HttpGet]
32         public ActionResult Index(int? year) {
33             if(Request.Cookies["allowed"] == null && !IsLocal())
34                 return Redirect("http://www.cpeonline.com/webcasts");
35             string systemPassword = ConfigurationManager.AppSettings["password"];
36             if(Request.Cookies["allowed"] != null && (Request.Cookies["allowed"].Value != systemPassword))
37                 return Redirect("http://www.cpeonline.com/webcasts");
38             DateTime now = DateTime.UtcNow;
39
40             if(!year.HasValue) {
41                 year = DateTime.Now.Year;
42             }
43
44             List<MeetingSessionsDataResult> meetingSessions = Database.MeetingSessionsData()
45                                                                       .Where(msd => msd.EndDate.HasValue && msd.EndDate <= now && (msd.StartDate >= new DateTime(year.Value, 1, 1) && msd.StartDate < new DateTime(year.Value + 1, 1, 1)))
46                                                                       .OrderByDescending(msd => msd.StartDate)
47                                                                       .ToList();
48             return View(meetingSessions);
49         }
50
51         [HttpGet]
52         public ActionResult SessionDetails(int meetingSessionKey) {
53             Extensions.LogServiceCall("[IndexController][SessionDetails]", string.Format("Beginning: meetingSessionKey = {0}", meetingSessionKey));
54
55             var meetingSession = Database.MeetingSessions.Single(ms => ms.MeetingSessionKey == meetingSessionKey);
56             var result = new AdobeSessionViewModel {
57                 MeetingSession = meetingSession,
58                 ParticipantSessionsDataResult = Database.ParticipantSessionsData(meetingSessionKey)
59                                                         .ToList(),
60                 GetSessionReportResult = Database.GetSessionReport(meetingSessionKey)
61                                                  .ToList(),
62                 WebcastPurchaseDataResult = Database.WebcastPurchaseData(meetingSession.SCO_ID, meetingSessionKey)
63                                                     //.Where(w => w.Sco == meetingSession.SCO_ID && w.mDate.DayOfYear >= meetingSession.StartDate.DayOfYear)
64                                                     .ToList()
65             };
66             //if (result.ParticipantSessionsDataResult.Count == 0) {
67             adobe.GetAdobeTransactions(meetingSession, Database);
68             Database.SubmitChanges();
69
70             result = new AdobeSessionViewModel {
71                 MeetingSession = meetingSession,
72                 ParticipantSessionsDataResult = Database.ParticipantSessionsData(meetingSessionKey)
73                                                         .ToList(),
74                 GetSessionReportResult = Database.GetSessionReport(meetingSessionKey)
75                                                  .ToList(),
76                 WebcastPurchaseDataResult = Database.WebcastPurchaseData(meetingSession.SCO_ID, meetingSessionKey)
77                                                     .ToList()
78             };
79             //}
80             return View(result);
81         }
82
83         [HttpGet]
84         public ActionResult RetrieveSession(int meetingSessionKey) {
85             Extensions.LogServiceCall("[IndexController][RetrieveSession]", string.Format("Beginning: meetingSessionKey = {0}", meetingSessionKey));
86
87             var meetingSession = Database.MeetingSessions.Single(ms => ms.MeetingSessionKey == meetingSessionKey);
88             if(Database.ParticipantSessionsData(meetingSessionKey)
89                        .ToList()
90                        .Count == 0) {
91                 adobe.GetAdobeTransactions(meetingSession, Database);
92                 Database.SubmitChanges();
93             }
94
95             return RedirectToAction("SessionDetails", new {meetingSessionKey});
96         }
97
98
99         [HttpGet]
100         public ActionResult TestElucidat()
101         {
102             var baseUrl = "https://api-launchpad.elucidat.com/";
103             var urlFull = "health/ping";
104             Extensions.LogServiceCall("[IndexController][TestElucidat]", $"Beginning: {baseUrl}{urlFull}");
105
106             ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
107             ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Tls;
108             ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Tls11;
109             // Add TLS 1.2
110             ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
111
112             var client = new WebClient { BaseAddress = baseUrl };
113             client.Headers.Clear();
114             client.Headers["Accept"] = "application/json";
115             var response = client.DownloadString(urlFull);
116             Extensions.LogServiceCall("[IndexController][TestElucidat]", $"Response: {response}");
117
118
119             return Content(response);
120         }
121
122         [HttpGet]
123         public ActionResult Login(string meetingUrl, string d = null, string c = null) {
124             meetingUrl = meetingUrl?.Trim();
125             d = d?.Trim();
126             c = c?.Trim();
127
128
129             Extensions.LogServiceCall("[IndexController][Login|Get]", string.Format("meetingUrl = {0} d (PurchaseDate) = {1} c (TicketFromUrl) = {2}", meetingUrl, d, c));
130
131             //Webcast and Rebroadcast access test course
132             if(meetingUrl.ToLower() == "test_room") {
133                 var baseUrl = ConfigurationManager.AppSettings["Connect.Url"];
134                 var testUrl = ConfigurationManager.AppSettings["Connect.AccessTestMeetingUrl"];
135                 var accessTestUrl = baseUrl + '/' + testUrl;
136                 return Redirect(accessTestUrl);
137             }
138             var meetingType = meetingUrl.Contains('-') ? MeetingType.Elucidat : MeetingType.Adobe;
139
140             if(meetingType == MeetingType.Elucidat) {
141                 var releaseCode = meetingUrl.Substring(meetingUrl.IndexOf('-') + 1);
142                 Extensions.LogServiceCall("[IndexController][Login|Get]", string.Format("meetingUrl = {0} releaseCode = {1}", meetingUrl, releaseCode));
143
144                 ReleaseModel release = ElucidatMeetingConnection.GetReleaseDetails(releaseCode);
145                 string projectName = null;
146                 if(release != null && release.Project != null) {
147                     projectName = release.Project.Name;
148                 }
149                 return View("elucidatlogin", new ElucidatCourseView {Name = projectName, Url = meetingUrl, PurchaseDate = d, TicketFromUrl = c, Message = null});
150             }
151             //if (ConfigurationManager.AppSettings["CPE.AdobeTicketingOn"].ToLower() == "true")
152             //{
153             //    //The flag is unnecessary now since we're keeping magic passcode access available. Non-ticketed link is now magicTicket 
154
155             // }
156
157             XmlDocument meeting = AdobeMeetingConnection.getAdobeMeeting(meetingUrl);
158             if(meeting != null) {
159                 if(meeting.SelectSingleNode("//sco")
160                           .Attributes["icon"].Value != "archive") {
161                     return View("login", new AdobeMeetingView {
162                         Name = meeting.SelectSingleNode("//sco/name")
163                                       .InnerText,
164                         HasPassCode = meeting.SelectSingleNode("//meeting-passcode") != null,
165                         PurchaseDate = d,
166                         TicketFromUrl = c
167                     });
168                 }
169             }
170             return null;
171         }
172
173         [HttpPost]
174         public ActionResult Login(string meetingUrl, string firstname, string lastname, string email, string passcode,
175                                   string courseName, string ticket = null, string ticketFromUrl = null, string purchaseDate = null,
176                                   string message = null) {
177             meetingUrl = meetingUrl?.Trim();
178             firstname = firstname?.Trim();
179             lastname = lastname?.Trim();
180             email = email?.Trim();
181             passcode = passcode?.Trim();
182             courseName = courseName?.Trim();
183             ticket = ticket?.Trim();
184             ticketFromUrl = ticketFromUrl?.Trim();
185             purchaseDate = purchaseDate?.Trim();
186             message = message?.Trim();
187
188             Extensions.LogServiceCall("[IndexController][Login|Post]", string.Format("email = {0} meetingUrl = {1} ticket = {2} ticketFromUrl = {3} purchaseDate = {4} firstname = {5} lastname = {6} passcode = {7} courseName = {8}", email, meetingUrl, ticket, ticketFromUrl, purchaseDate, firstname, lastname, passcode, courseName));
189
190             var magicTicketLogin = string.IsNullOrEmpty(ticketFromUrl);
191             var meetingType = meetingUrl.Contains('-') ? MeetingType.Elucidat : MeetingType.Adobe;
192
193             if(meetingType.Equals(MeetingType.Elucidat)) {
194                 var releaseCode = meetingUrl.Substring(meetingUrl.IndexOf('-') + 1);
195
196                 if(!ticket.Equals(ticketFromUrl) ||
197                    !VerifyAccess.VerifyTicket(ticket, meetingUrl, firstname, lastname, email, purchaseDate)) {
198                     return View("elucidatlogin", new ElucidatCourseView {
199                         Url = meetingUrl,
200                         Name = courseName,
201                         PurchaseDate = purchaseDate,
202                         TicketFromUrl = ticketFromUrl,
203                         Message =
204                             "Invalid Login. Please re-enter your information. This information MUST match the information in the email you received with your passcode. If you continue to have trouble, please contact Customer Service at 1-800-544-1114 or email us at sswebcast@cpeincmail.com"
205                     }
206                         );
207                 }
208
209                 PurchasedCourse course =
210                     Database.PurchasedCourses.SingleOrDefault(pc => pc.Ticket == ticket && pc.ContentUrl == meetingUrl);
211
212                 if(course == null) {
213                     //no purchase record yet, look for release details in database
214                     CourseDetail release = Database.CourseDetails.SingleOrDefault(r => r.ReleaseCode == releaseCode);
215                     if(release == null) {
216                         //course isn't in db yet, get details form api
217                         ReleaseModel releaseCourse = ElucidatMeetingConnection.GetReleaseDetails(releaseCode);
218                         var done = ReleaseHelper.GetReleaseDescriptionDetails(releaseCourse);
219                         if(done) {
220                             release = Database.CourseDetails.SingleOrDefault(cd => cd.ReleaseCode == releaseCode);
221                         }
222                     }
223                     string formattedPdate = purchaseDate.Substring(0, 4) + '-' + purchaseDate.Substring(4, 2) + '-' +
224                                             purchaseDate.Substring(6, 2);
225                     DateTime pDate = Convert.ToDateTime(formattedPdate);
226                     course = new PurchasedCourse {
227                         ContentUrl = meetingUrl,
228                         CourseName = release.Name,
229                         FirstName = firstname,
230                         LastName = lastname,
231                         Email = email,
232                         Ticket = ticket,
233                         PurchaseDate = pDate,
234                         Presenter = release.Presenter,
235                         Fos = release.Fos,
236                         Credits = release.Credits,
237                         CertificateDate = null,
238                         FailedAttempts = 0,
239                         isManualCertificate = false
240                     };
241                     Database.PurchasedCourses.InsertOnSubmit(course);
242                 }
243
244                 Database.SubmitChanges();
245
246                 //verify access (PurchaseDate<1yrold) and access not revoked
247                 if(!VerifyAccess.AccessBlocked(course) && VerifyAccess.IsValid(course)) {
248                     string courseUrl = ElucidatMeetingConnection.GetLaunchLink(releaseCode, firstname, lastname, email);
249
250                     Regex linkParser = new Regex(@"\b(?:https?://)\S+\b",
251                                                  RegexOptions.Compiled | RegexOptions.IgnoreCase);
252                     string rawString = courseUrl;
253                     string goodUrl = linkParser.Match(rawString)
254                                                .Value;
255
256                     return Redirect(goodUrl);
257                 }
258
259                 //Access is expired or Revoked
260                 return View("elucidatlogin", new ElucidatCourseView {
261                     Url = meetingUrl,
262                     Name = courseName,
263                     PurchaseDate = purchaseDate,
264                     TicketFromUrl = ticketFromUrl,
265                     Message =
266                         "Access to this course is no longer available. Please contact Customer Service at 1-800-544-1114 or email us at sswebcast@cpeincmail.com"
267                 }
268                     );
269             }
270             if((ConfigurationManager.AppSettings["CPE.AdobeTicketingOn"].ToLower() == "true") & !magicTicketLogin) {
271                 if(passcode == null) {
272                     passcode = (DateTime.UtcNow.ToString("MMM") + DateTime.UtcNow.Day.ToString("00")).ToLower();
273                 }
274                 if(!ticketFromUrl.Equals(ticket)) {
275                     return RedirectToAction("Login");
276                 }
277                 if(!VerifyAccess.VerifyTicket(ticket, meetingUrl, firstname, lastname, email, purchaseDate)) {
278                     return RedirectToAction("Login");
279                 }
280
281                 //if valid continue on to existing way of doing things
282             }
283
284             string connectUrl = ConfigurationManager.AppSettings["Connect.Url"];
285             int accountId = int.Parse(ConfigurationManager.AppSettings["Connect.AccountId"]);
286             string password = Guid.NewGuid()
287                                   .ToString()
288                                   .Replace("{", "")
289                                   .Replace("}", "")
290                                   .Substring(0, 8);
291             Session admin = AdobeMeetingConnection.GetAdobeAdminSession();
292             var request = new Request(admin, "principal-list");
293             request.Parameters.Add("filter-type", "guest");
294             request.Parameters.Add("filter-type", "user");
295             request.Parameters.Add("filter-login", email);
296             if(request.Execute() && request.Status == Status.OK) {
297                 Extensions.LogServiceCall("[IndexController][Login|Post]", string.Format("email = [{0}] request.XmlResults.InnerXml = {1}", email, request.XmlResults.InnerXml));
298
299                 int principalId;
300                 if(request.XmlResults.SelectSingleNode("//principal") == null) {
301                     principalId = Connect.Login.CreateGuest(admin, email, password, email, firstname, lastname);
302                 } else {
303                     principalId = int.Parse(request.XmlResults.SelectSingleNode("//principal")
304                                                    .Attributes["principal-id"].Value);
305                     email = request.XmlResults.SelectSingleNode("//principal/login")
306                                    .InnerText;
307                     if(request.XmlResults.SelectSingleNode("//principal")
308                               .Attributes["type"].Value == "user")
309                         return RedirectToAction("Login");
310                 }
311                 if(principalId < 1)
312                     return RedirectToAction("Login");
313
314
315                 Connect.Login.ResetPassword(admin, principalId, password);
316                 Session session = Connect.Login.UserLogin(email, password, connectUrl, accountId);
317
318                 var meetingView = new AdobeMeetingView {
319                     Name = AdobeMeetingConnection.getAdobeMeetingName(meetingUrl),
320                     PrincipalId = principalId,
321                     Url =
322                         string.Format("{0}/{1}?session={2}&launcher=false", connectUrl, meetingUrl,
323                                       session.SessionKey) + (passcode == null
324                                                                  ? ""
325                                                                  : "&meeting-passcode=" + passcode)
326                 };
327
328
329                 Participant participant = Database.Participants.SingleOrDefault(p => p.Principal_ID == principalId);
330                 if(participant == null) {
331                     participant = new Participant {
332                         Principal_ID = principalId,
333                         FirstName = firstname,
334                         LastName = lastname,
335                         Email = email
336                     };
337                     Database.Participants.InsertOnSubmit(participant);
338                 }
339
340                 Database.SubmitChanges();
341
342                 var certificateId = 0;
343                 int scoId = AdobeMeetingConnection.getAdobeMeetingSco(meetingUrl);
344
345                 if(!magicTicketLogin) {
346                     string formattedPdate = purchaseDate.Substring(0, 4) + '-' +
347                                             purchaseDate.Substring(4, 2) +
348                                             '-' + purchaseDate.Substring(6, 2);
349                     DateTime pDate = Convert.ToDateTime(formattedPdate);
350
351                     ParticipantPurchase purchase =
352                         Database.ParticipantPurchases.SingleOrDefault(
353                                                                       p =>
354                                                                       p.PrincipalID == principalId & p.Ticket == ticketFromUrl &
355                                                                       p.MeetingSco == scoId);
356                     if(purchase == null) {
357                         purchase = new ParticipantPurchase {
358                             FirstName = firstname,
359                             LastName = lastname,
360                             Email = email,
361                             PrincipalID = principalId,
362                             MeetingName = meetingView.Name,
363                             MeetingDate = DateTime.UtcNow,
364                             MeetingSco = scoId,
365                             Ticket = ticketFromUrl,
366                             PurchaseDate = pDate,
367                             EarnedCertificate = false,
368                             Credits = 0
369                         };
370                         Database.ParticipantPurchases.InsertOnSubmit(purchase);
371
372                         Extensions.LogServiceCall("[IndexController][Login|Post]", string.Format("email = {0} scoId = {1} principalId = {2} MeetingDate = {3}", email, scoId, principalId, purchase.MeetingDate));
373                     }
374
375                     Database.SubmitChanges();
376                     certificateId = purchase.Purchase_ID;
377                 }
378                 meetingView.CertificateId = certificateId;
379                 meetingView.ScoId = scoId;
380
381                 Extensions.LogServiceCall("[IndexController][Login|Post]", string.Format("email = {0} scoId = {1} certificateId = {2} principalId = {3}", email, scoId, certificateId, principalId));
382
383                 var idCookie = new HttpCookie("id") {
384                     Value = principalId.ToString(),
385                     Expires = DateTime.UtcNow.AddDays(1)
386                 };
387                 Response.Cookies.Add(idCookie);
388
389
390                 request = new Request(admin, "principal-update");
391                 request.Parameters.Add("first-name", firstname);
392                 request.Parameters.Add("last-name", lastname);
393                 request.Parameters.Add("principal-id", principalId.ToString());
394                 request.Execute();
395
396                 return View("meeting", meetingView);
397             }
398             return RedirectToAction("Login");
399         }
400
401         [HttpGet]
402         public ActionResult Admin() {
403             return View();
404         }
405
406         public ActionResult Email() {
407             var email = new MailMessage {
408                 To = {
409                     "tallen@intesolv.com"
410                 },
411                 Subject = "[CPE] Email Test",
412                 Body = "Email test has been received.",
413                 From = new MailAddress("support@intesolv.com")
414             };
415             var server = new SmtpClient("localhost");
416             server.Send(email);
417
418             return Redirect("/");
419         }
420
421         [HttpPost]
422         public ActionResult Admin(string login, string passcode) {
423             login = login?.Trim();
424             passcode = passcode?.Trim();
425
426             string systemPassword = ConfigurationManager.AppSettings["password"];
427             if(login == ConfigurationManager.AppSettings["login"] & passcode == systemPassword) {
428                 var reportingCookie = new HttpCookie("allowed") {
429                     Value = systemPassword,
430                     Expires = DateTime.UtcNow.AddDays(1)
431                 };
432                 Response.Cookies.Add(reportingCookie);
433             }
434             return Redirect("/");
435         }
436
437         [HttpGet]
438         public ActionResult CourseDetails(string releaseCode) {
439             releaseCode = releaseCode?.Trim();
440
441             var course = Database.CourseDetails.Single(cd => cd.ReleaseCode == releaseCode);
442             var result = new ElucidatCourseViewModel {
443                 CourseDetail = course,
444                 PurchasedCoursesDataResult = Database.PurchasedCoursesData(releaseCode)
445                                                      .OrderByDescending(pc => pc.PurchaseDate)
446                                                      .ToList()
447             };
448
449             return View(result);
450         }
451
452         [HttpGet]
453         public ActionResult Elucidat() {
454             if(Request.Cookies["allowed"] == null && !IsLocal())
455                 return Redirect("http://www.cpeonline.com/webcasts");
456             string systemPassword = ConfigurationManager.AppSettings["password"];
457             if(Request.Cookies["allowed"] != null && (Request.Cookies["allowed"].Value != systemPassword))
458                 return Redirect("http://www.cpeonline.com/webcasts");
459             DateTime now = DateTime.UtcNow;
460
461             List<CourseListingsDataResult> courseListings = Database.CourseListingsData()
462                                                                     .Where(cl => cl.CreatedDate != null)
463                                                                     .OrderBy(cl => cl.Name)
464                                                                     .ToList();
465             return View(courseListings);
466         }
467
468         [HttpGet]
469         public ActionResult Wufoo(int id) {
470             //https://cpeonline.wufoo.com/forms/cpe-webcast-evaluation/def/Field1=Jason&Field2=Wigginton&Field3-1=7&Field3-2=2&Field3=2012&Field4=1234&Field5=J.%20McIntosh&Field6=ConnectPro&Field7=Test101&Field8=Test%20topic
471             ParticipantTracking pt = Database.ParticipantTrackings.OrderByDescending(p => p.StartDate)
472                                              .FirstOrDefault(p => p.Principal_ID == id);
473             string url = ConfigurationManager.AppSettings["Wufoo.Survey1.1"];
474             if(pt == null) {
475                 Extensions.LogServiceCall("[IndexController][Wufoo]", string.Format("id = {0} url = {1}", id, url));
476                 return Redirect(url);
477             }
478
479             MeetingDetail d = pt.MeetingParticipantSession.MeetingSession.Meeting.MeetingDetail;
480             DateTime date = Extensions.GetLocalDateTime(DateTime.UtcNow);
481             url += string.Format(ConfigurationManager.AppSettings["Wufoo.Survey1.2"], pt.Participant.FirstName, pt.Participant.LastName, date.Month.ToString("00"), date.Day.ToString("00"), date.Year, d.TopicID, d.TopicName, d.Instructor, d.Location, d.CourseCode);
482             Extensions.LogServiceCall("[IndexController][Wufoo]", string.Format("id = {0} url = {1}", id, url));
483             return Redirect(url);
484         }
485
486         public ActionResult Survey() {
487             int id = 0;
488             string url = ConfigurationManager.AppSettings["Wufoo.Survey1.1"];
489             string cookie = Request.Cookies["id"] == null
490                                 ? "0"
491                                 : Request.Cookies["id"].Value;
492             int.TryParse(cookie, out id);
493             if(id == 0) {
494                 return Redirect(url);
495             }
496             Extensions.LogServiceCall("[IndexController][Survey]", string.Format("id = {0}", id));
497             ParticipantTracking pt = Database.ParticipantTrackings.OrderByDescending(p => p.StartDate)
498                                              .FirstOrDefault(p => p.Principal_ID == id);
499             if(pt == null)
500                 return Redirect(url);
501
502             MeetingDetail d = pt.MeetingParticipantSession.MeetingSession.Meeting.MeetingDetail;
503             DateTime date = Extensions.GetLocalDateTime(DateTime.UtcNow);
504             url += string.Format(ConfigurationManager.AppSettings["Wufoo.Survey1.2"], pt.Participant.FirstName, pt.Participant.LastName, date.Month.ToString("00"), date.Day.ToString("00"), date.Year, d.TopicID, d.TopicName, d.Instructor, d.Location, d.CourseCode);
505             return Redirect(url);
506         }
507
508         [HttpGet]
509         public ActionResult AllowReporting(Guid? id) {
510             //if (id.HasValue && id == Guid.Parse("")) {
511             //    var reportingCookie = new HttpCookie("reporting") {Value = "1", Expires = DateTime.MaxValue};
512             //    Response.Cookies.Add(reportingCookie);
513             //    return Redirect("/");
514             //}
515             //return Redirect("http://www.cpeonline.com/webcasts");
516             return RedirectToAction("Admin");
517         }
518
519         [HttpGet]
520         public ActionResult GetTicket(string courseUrl) {
521             courseUrl = courseUrl?.Trim();
522
523             TicketModel ticketInfo = new TicketModel {
524                 CourseUrl = courseUrl
525             };
526             //return the view as a partial view that opens in a pretty jquery ui form (dialog) within the page, not a new page
527             return PartialView(ticketInfo);
528         }
529
530         [HttpPost]
531         public string GetTicket(string firstname, string lastname, string email, string contenturl) {
532             //NOT IMPLEMENTED. possible solution to "magic ticket" request for ondemand course, since a global entry would not make sense
533             //generate hashed ticket link for a specific user for an ondemand course. This will bypass cpe's commerce site and allow cpe customer service to generate an access link
534
535             firstname = firstname?.Trim();
536             lastname = lastname?.Trim();
537             email = email?.Trim();
538             contenturl = contenturl?.Trim();
539
540             string purchasedate = DateTime.Now.ToString("yyyyMMdd");
541             var ticket = VerifyAccess.generateTicket(contenturl, firstname, lastname, email, purchasedate);
542
543             var link = "http://cpeonlineselfstudywebcasts.com/" + contenturl + "?d=" + purchasedate + "&c=" + ticket;
544             return link;
545         }
546
547         // GET: CertificateReport
548         [HttpGet]
549         public ActionResult CertificateReport() {
550             List<CertficateDataResult> earnedCertificates = Database.CertficateData()
551                                                                     .OrderBy(ec => ec.Course)
552                                                                     .ToList();
553             return View(earnedCertificates);
554         }
555
556         public ActionResult WebcastCertificateReport() {
557             List<WebcastCertficateDataResult> earnedCertificates = Database.WebcastCertficateData()
558                                                                            .OrderBy(ec => ec.MeetingName)
559                                                                            .ToList();
560             return View(earnedCertificates);
561         }
562
563         //public string SendCert(int meeting_sco, int certificate_id, int principal_id)
564         //{
565         //    //TODO (webcast) make outcome dictionary to return pass, fail, ineligible, or wonky:contact cust serv
566         //    string _fail = "fail";
567         //    if (certificate_id > 0)
568         //    {
569         //        ParticipantPurchase purchase =
570         //            Database.ParticipantPurchases.FirstOrDefault(p => p.Purchase_ID == certificate_id && p.PrincipalID == principal_id);
571
572         //        if (purchase == null)
573         //        {
574         //            //if the certificate_id is >0 then purchase would only be null because of record being deleted while user was in the meeting, or the principalID got mis-matched
575         //            return _fail; // TODO probably return wonky, contact cust service message
576         //        }
577
578         //        if (!purchase.EarnedCertificate)
579         //        {
580         //            var meeting = Database.MeetingSessions.FirstOrDefault(
581         //                    m =>
582         //                        m.Recording == false && m.SCO_ID == meeting_sco &&
583         //                        m.StartDate.DayOfYear == DateTime.UtcNow.DayOfYear);
584         //            if (meeting == null)
585         //            {
586         //                return _fail;//TODO return wonky
587         //            }
588
589         //            int meetingSessionKey = meeting.MeetingSessionKey;
590
591         //            MeetingParticipantSession meetingParticipantSession =
592         //                Database.MeetingParticipantSessions.FirstOrDefault(
593         //                    m => m.MeetingSessionKey == meetingSessionKey && m.ParticipantKey == principal_id);
594         //            if (meetingParticipantSession == null)
595         //            {
596         //                return _fail;//TODO return wonky
597         //            }
598
599         //            List<ParticipantSessionsDataResult> participantSessionsDataResult =
600         //                Database.ParticipantSessionsData(meetingSessionKey)
601         //                    .ToList();
602
603         //            var participantSessionsData =
604         //                participantSessionsDataResult.OrderBy(p => p.MeetingParticipantSessionKey)
605         //                    .FirstOrDefault(
606         //                        p =>
607         //                            p.MeetingParticipantSessionKey ==
608         //                            meetingParticipantSession.MeetingParticipantSessionKey);
609
610         //            if (participantSessionsData == null)
611         //            {
612         //                return _fail;//TODO is this a return wonky? it means they weren't tracked
613         //            }
614
615         //            MeetingSessionsDataResult meetingSession = Database.MeetingSessionsData().FirstOrDefault(m => m.MeetingSessionKey == meetingSessionKey);
616         //            if (meetingSession == null)
617         //            {
618         //                return _fail;//TODO return wonky
619         //            }
620
621         //            var courseLength = meetingSession.ActualSessionTime.GetValueOrDefault(); //in minutes
622         //            double courseCredits = courseLength / 50.0; //1 credit per 50 minutes
623         //            List<double> maxCourseCredits = ConfigurationManager.AppSettings["MaxCourseCreditList"].Split(';').Select(s => double.Parse(s)).ToList(); //max credits cut list
624         //            int mx = maxCourseCredits.BinarySearch(courseCredits); //find appropriate max for this course
625         //            double maxCredits = maxCourseCredits[mx >= 0 ? mx : ~mx - 1];//...by rounding down
626         //            double realCredits = participantSessionsData.SessionCredit == null ? 0 : (double)participantSessionsData.SessionCredit.Value; //users credits per adobe
627         //            purchase.Credits = Math.Min(maxCredits, realCredits); //user awarded no more than max possible credits for the course
628
629         //            MeetingDetail meetingDetail =
630         //                Database.MeetingDetails.FirstOrDefault(m => m.MeetingKey == purchase.MeetingSco);
631
632         //            purchase.Presenter = meetingDetail == null ? "" : meetingDetail.Instructor;
633
634         //            double percentComplete = (participantSessionsData.SessionEngagementCount.GetValueOrDefault() == 0 ? 
635         //                    1 : (participantSessionsData.SessionHeartbeatCount.GetValueOrDefault() / participantSessionsData.SessionEngagementCount.Value));
636
637         //            if (percentComplete >= .75) //threshold for earning a certificate is 75% response rate
638         //            {
639         //                purchase.EarnedCertificate = true;
640         //            }
641
642         //            Database.SubmitChanges();
643
644         //            if (purchase.EarnedCertificate)
645         //            {
646         //                //TODO with return Pass dictionary value as string.format with replace of certUrl
647         //                //string certUrl = AdobeCertificateHelper.SendWebcastCert(purchase);
648         //                //format the outcome.pass.value message with certUrl replace
649         //                //return outcome.pass with its value
650         //                return AdobeCertificateHelper.SendWebcastCert(purchase);
651         //            }
652         //            //TODO return outcome.fail
653         //            return AdobeCertificateHelper.SendFailNotice(purchase);
654         //        }
655         //    }
656         //    return _fail;// TODO return ineligible.need to make AdobeCertificateHelper.SendIneligibleNotice(principalId)
657         //}
658
659         //public participantResult ProcessParticipantResult(participantResult result, ParticipantPurchase purchase)
660         //{
661         //    if (purchase == null)
662         //    {
663         //        result = participantResult.Ineligible;
664         //    }
665         //    switch (result)
666         //    {
667         //        case participantResult.Ineligible:
668         //            //Ineligible for auto-cert; not sending notice.  
669         //            break;
670         //        case participantResult.Fail:
671         //            AdobeCertificateHelper.SendFailNotice(purchase);
672         //            break;
673         //        case participantResult.Pass:
674         //            AdobeCertificateHelper.SendWebcastCert(purchase);
675         //            //Send Cert email;
676         //            break;
677         //        case participantResult.Wonky:
678         //            //something went wrong: send email to contact cust service? send email to cpe? do nothing? 
679         //            break;
680         //    }
681         //    return result;
682         //}
683
684         //public ActionResult BatchProcessParticipantResults(int msk)
685         //{
686         //    List<ParticipantSessionsDataResult> psdr = BaseController.Database.ParticipantSessionsData(msk).ToList();
687         //    var meeting = BaseController.Database.MeetingSessions.FirstOrDefault(m => m.MeetingSessionKey == msk);
688         //    if (meeting == null)
689         //    {
690         //        return Content("Error retrieving meeting session details.");
691         //    }
692         //    var scoId = meeting.SCO_ID;
693
694         //    foreach (var p in psdr)
695         //    {
696         //        ParticipantPurchase purchase = null;
697         //        participantResult result = participantResult.Wonky;
698         //        var mpsk = p.MeetingParticipantSessionKey;
699         //        var meetingParticipantSession =
700         //            BaseController.Database.MeetingParticipantSessions.FirstOrDefault(
701         //                mps => mps.MeetingParticipantSessionKey == mpsk && mps.MeetingSessionKey == msk);
702
703         //        if (meetingParticipantSession != null)
704         //        {
705         //            var principalId = meetingParticipantSession.ParticipantKey;
706
707         //            purchase = BaseController.Database.ParticipantPurchases.FirstOrDefault(pp => pp.PrincipalID == principalId && pp.MeetingSco == scoId);
708         //            if (purchase == null)
709         //            {
710         //                result = participantResult.Ineligible;
711         //            }
712         //            else
713         //            {
714         //                MeetingSessionsDataResult meetingSession = Database.MeetingSessionsData().FirstOrDefault(m => m.MeetingSessionKey == msk);
715         //                if (meetingSession != null)
716         //                {
717         //                    var courseLength = meetingSession.ActualSessionTime.GetValueOrDefault(); //in minutes
718         //                    double courseCredits = courseLength/50.0; //1 credit per 50 minutes
719         //                    List<double> maxCourseCredits =
720         //                        ConfigurationManager.AppSettings["MaxCourseCreditList"].Split(';')
721         //                            .Select(s => double.Parse(s))
722         //                            .ToList(); //max credits cut list
723         //                    int mx = maxCourseCredits.BinarySearch(courseCredits);
724         //                        //find appropriate max for this course
725         //                    double maxCredits = maxCourseCredits[mx >= 0 ? mx : ~mx - 1]; //...by rounding down
726         //                    double realCredits = p.SessionCredit == null
727         //                        ? 0
728         //                        : (double) p.SessionCredit.Value; //users credits
729         //                    purchase.Credits = Math.Min(maxCredits, realCredits);
730         //                        //user awarded no more than max possible credits for the course
731
732         //                    MeetingDetail meetingDetail =
733         //                        Database.MeetingDetails.FirstOrDefault(m => m.MeetingKey == purchase.MeetingSco);
734
735         //                    purchase.Presenter = meetingDetail == null ? "" : meetingDetail.Instructor;
736
737         //                    double percentComplete =
738         //                        (p.SessionEngagementCount.GetValueOrDefault() == 0
739         //                            ? 1
740         //                            : (p.SessionHeartbeatCount.GetValueOrDefault()/
741         //                               p.SessionEngagementCount.Value));
742
743         //                    if (percentComplete >= .75) //threshold for earning a certificate is 75% response rate
744         //                    {
745         //                        purchase.EarnedCertificate = true;
746         //                        result = participantResult.Pass;
747         //                    }
748         //                    else
749         //                    {
750         //                        result = participantResult.Fail;
751         //                    }
752
753         //                    Database.SubmitChanges();
754         //                }
755         //            }
756         //        }
757         //        ProcessParticipantResult(result, purchase);
758         //    }
759         //    return Content("done");
760         //}
761
762         public ActionResult Result(int principalid, int scoid) {
763             var resultView = new SessionResultViewModel();
764             participantResult result = participantResult.Wonky;
765
766             Extensions.LogServiceCall("[IndexController][Result]", string.Format("Beginning: principalid = {0} scoid = {1}", principalid, scoid));
767
768             Extensions.LogServiceCall("[IndexController][Result]", string.Format(
769                                                                                  "principalid = {0} scoid = {1} DateTime.UtcNow.DayOfYear = {2} DateTime.Now.DayOfYear = {3}",
770                                                                                  principalid, scoid, DateTime.UtcNow.DayOfYear, DateTime.Now.DayOfYear));
771
772             var meeting =
773                 Database.MeetingSessions.FirstOrDefault(
774                                                         m => m.SCO_ID == scoid && m.StartDate.DayOfYear == DateTime.UtcNow.DayOfYear);
775             if(meeting != null) {
776                 int msk = meeting.MeetingSessionKey;
777                 MeetingParticipantSession meetingParticipantSession =
778                     Database.MeetingParticipantSessions.FirstOrDefault(
779                                                                        m => m.MeetingSessionKey == msk && m.ParticipantKey == principalid);
780                 if(meetingParticipantSession != null) {
781                     adobe.GetAdobeTransactions(meetingParticipantSession.MeetingSession, Database);
782                     Database.SubmitChanges();
783
784                     result = SessionEnd.ProcessEndOfMeetingSessionHeartbeatResultsForParticipant(Database, meetingParticipantSession);
785                     switch (result) {
786                         case participantResult.Ineligible:
787                             resultView.Message = Utilities.Result.RenderIneligibleResult(principalid);
788                             break;
789                         case participantResult.Fail:
790                             resultView.Message = Utilities.Result.RenderFailResult(principalid);
791                             break;
792                         case participantResult.Pass:
793                             resultView.Message = Utilities.Result.RenderPassResult(principalid);
794                             break;
795                         case participantResult.Wonky:
796                             resultView.Message = Utilities.Result.RenderWonkyResult();
797                             break;
798                     }
799                 } else {
800                     Extensions.LogServiceCall("[IndexController][Result]", string.Format(
801                                                                                          "meetingParticipantSession is null: principalid = {0} scoid= {1} msk = {2}",
802                                                                                          principalid, scoid, msk));
803                 }
804             } else {
805                 Extensions.LogServiceCall("[IndexController][Result]", string.Format(
806                                                                                      "meeting is null: principalid = {0} scoid= {1} DateTime.UtcNow.DayOfYear = {2} DateTime.Now.DayOfYear = {3}",
807                                                                                      principalid, scoid, DateTime.UtcNow.DayOfYear, DateTime.Now.DayOfYear));
808             }
809             resultView.Result = (int) result;
810             return View("result", resultView);
811         }
812     }
813 }