public static bool SendCurrentIncidentInvoiceEmail(Incident incident, ApiServices Services)
        {
            IncidentInfo invoiceIncident = new IncidentInfo(incident);

            if (invoiceIncident.PaymentAmount < invoiceIncident.ServiceFee)
            {

                SendGridMessage invoiceMessage = new SendGridMessage();

                invoiceMessage.From = SendGridHelper.GetAppFrom();
                invoiceMessage.AddTo(invoiceIncident.IncidentUserInfo.Email);
                invoiceMessage.Html = " ";
                invoiceMessage.Text = " ";
                invoiceMessage.Subject = "StrandD Invoice - Payment for Service Due";

                invoiceMessage.EnableTemplateEngine(WebConfigurationManager.AppSettings["RZ_InvoiceTemplateID"]);
                invoiceMessage.AddSubstitution("%invoicestub%", new List<string> { invoiceIncident.IncidentGUID.Substring(0, 5).ToUpper() });
                invoiceMessage.AddSubstitution("%incidentguid%", new List<string> { invoiceIncident.IncidentGUID });
                invoiceMessage.AddSubstitution("%name%", new List<string> { invoiceIncident.IncidentUserInfo.Name });
                invoiceMessage.AddSubstitution("%phone%", new List<string> { invoiceIncident.IncidentUserInfo.Phone });
                invoiceMessage.AddSubstitution("%email%", new List<string> { invoiceIncident.IncidentUserInfo.Email });
                invoiceMessage.AddSubstitution("%jobdescription%", new List<string> { invoiceIncident.JobCode });
                invoiceMessage.AddSubstitution("%servicefee%", new List<string> { (invoiceIncident.ServiceFee - invoiceIncident.PaymentAmount).ToString() });
                invoiceMessage.AddSubstitution("%datesubmitted%", new List<string> { DateTime.Now.ToShortDateString() });
                invoiceMessage.AddSubstitution("%datedue%", new List<string> { (DateTime.Now.AddDays(30)).ToShortTimeString() });
                invoiceMessage.AddSubstitution("%servicepaymentlink%", new List<string> { (WebConfigurationManager.AppSettings["RZ_ServiceBaseURL"].ToString() + "/view/customer/incidentpayment/" + invoiceIncident.IncidentGUID) });

                // Create an Web transport for sending email.
                var transportWeb = new Web(SendGridHelper.GetNetCreds());

                // Send the email.
                try
                {
                    transportWeb.Deliver(invoiceMessage);
                    Services.Log.Info("Incident Invoice Email Sent to [" + invoiceIncident.IncidentUserInfo.Email + "]");
                    return true;
                }
                catch (InvalidApiRequestException ex)
                {
                    for (int i = 0; i < ex.Errors.Length; i++)
                    {
                        Services.Log.Error(ex.Errors[i]);
                        return false;
                    }
                }
                return false;

            }
            else
            {
                return false;
            }
        }
        public IncidentExcelData(Incident baseIncident)
        {
            stranddContext context = new stranddContext();

            // Pull Incident data
            this.TimeStamp = (baseIncident.CreatedAt != null) ? (DateTimeOffset) baseIncident.CreatedAt : DateTimeOffset.MinValue;
            this.IncidentGUID = baseIncident.Id;
            this.JobCode = baseIncident.JobCode;
            this.ArrivalTime = System.Convert.ToString(baseIncident.ProviderArrivalTime);
            this.ConcertoCaseID = baseIncident.ConcertoCaseID;
            this.StaffNotes = baseIncident.StaffNotes;
            this.ServiceFee = System.Convert.ToString(baseIncident.ServiceFee);
            this.CustomerComments = baseIncident.CustomerComments;
            this.CustomerRating = baseIncident.Rating.ToString();
            this.IncidentStatus = baseIncident.StatusCode;

            //pull customer Data
            AccountInfo lookupCustomer = new AccountInfo(baseIncident.ProviderUserID);
            this.CustomerName = lookupCustomer.Name;
            this.CustomerPhone = lookupCustomer.Phone;

            //pull Vehicle data
            VehicleInfo lookupVehicle = new VehicleInfo(baseIncident.VehicleGUID);
            this.VehicleDescription = lookupVehicle.Year + " " + lookupVehicle.Color + " " + lookupVehicle.Make + " " + lookupVehicle.Model;
            this.VehicleRegistration = lookupVehicle.RegistrationNumber;

            //Pull Payment data

            Payment lookupPayment = context.Payments
            .Where(u => u.IncidentGUID == baseIncident.Id)
            .FirstOrDefault();
            this.PaymentStatus = (lookupPayment != null) ? lookupPayment.Status : null;
            this.PaymentAmount = (lookupPayment != null) ? lookupPayment.Amount : 0;
            this.PaymentPlatform = (lookupPayment != null) ? lookupPayment.PaymentPlatform : null;

            //Pull Admin from History Event

            HistoryEvent lookupAdminEvent = context.HistoryLog
              .Where(u => u.ReferenceID == baseIncident.Id)
              .Where(v => v.Code == "INCIDENT_STATUS_ADMIN")
              .Where(x => x.Attribute == "CONFIRMED")
              .FirstOrDefault();

            AccountInfo lookupAdmin;
            if (lookupAdminEvent != null) { lookupAdmin = new AccountInfo(lookupAdminEvent.AdminID); }
            else { lookupAdmin = new AccountInfo(null); }
            this.ConfirmedAdminName = lookupAdmin.Name;
        }
        public static void ProcessStatusRequestBehavior(IncidentStatusRequest statusRequest, Incident updateIncident, ApiServices Services)
        {
            IHubContext hubContext = Services.GetRealtime<IncidentHub>();

            switch (updateIncident.StatusCode)
            {
                case "PROVER-FOUND":

                    //Notify Particular Connected User through SignalR
                    hubContext.Clients.Group(updateIncident.ProviderUserID).updateMobileClientStatus(statusRequest.GetCustomerPushObject());
                    Services.Log.Info("Mobile Client [" + updateIncident.ProviderUserID + "] Status Update Payload Sent");

                    //Notifying Connect WebClients with IncidentInfo Package            
                    hubContext.Clients.All.updateIncidentStatusAdmin(new IncidentInfo(updateIncident));
                    Services.Log.Info("Connected Clients Updated");

                    RevokeProviderJobs(updateIncident, Services);
                    Services.Log.Info("Provider Jobs Revoked");

                    break;

                case "ARRIVED":
                    
                    //Notify Particular Connected User through SignalR
                    hubContext.Clients.Group(updateIncident.ProviderUserID).updateMobileClientStatus(statusRequest.GetCustomerPushObject());
                    Services.Log.Info("Mobile Client [" + updateIncident.ProviderUserID + "] Status Update Payload Sent");

                    //Notifying Connect WebClients with IncidentInfo Package            
                    hubContext.Clients.All.updateIncidentStatusAdmin(new IncidentInfo(updateIncident));
                    Services.Log.Info("Connected Clients Updated");

                    SendGridController.SendCurrentIncidentInvoiceEmail(updateIncident, Services);

                    break;

                case "COMPLETED":

                    //Notify Particular Connected User through SignalR
                    hubContext.Clients.Group(updateIncident.ProviderUserID).updateMobileClientStatus(statusRequest.GetCustomerPushObject());
                    Services.Log.Info("Mobile Client [" + updateIncident.ProviderUserID + "] Status Update Payload Sent");

                    //Notifying Connect WebClients with IncidentInfo Package            
                    hubContext.Clients.All.updateIncidentStatusAdmin(new IncidentInfo(updateIncident));
                    Services.Log.Info("Connected Clients Updated");
                    break;

                case "DECLINED":

                    //Notify Particular Connected User through SignalR
                    hubContext.Clients.Group(updateIncident.ProviderUserID).updateMobileClientStatus(statusRequest.GetCustomerPushObject());
                    Services.Log.Info("Mobile Client [" + updateIncident.ProviderUserID + "] Status Update Payload Sent");

                    //Notifying Connect WebClients with IncidentInfo Package            
                    hubContext.Clients.All.updateIncidentStatusAdmin(new IncidentInfo(updateIncident));
                    Services.Log.Info("Connected Clients Updated");

                    RevokeProviderJobs(updateIncident, Services);
                    Services.Log.Info("Provider Jobs Revoked");

                    break;

                case "CANCELLED":
                    //Notifying Connect WebClients with IncidentInfo Package            
                    hubContext.Clients.All.updateIncidentStatusCustomerCancel(new IncidentInfo(updateIncident));
                    Services.Log.Info("Connected Clients Updated");

                    RevokeProviderJobs(updateIncident, Services);
                    Services.Log.Info("Provider Jobs Revoked");

                    break;

                default:
                    //Notify Particular Connected User through SignalR
                    hubContext.Clients.Group(updateIncident.ProviderUserID).updateMobileClientStatus(statusRequest.GetCustomerPushObject());
                    Services.Log.Info("Mobile Client [" + updateIncident.ProviderUserID + "] Status Update Payload Sent");

                    //Notifying Connect WebClients with IncidentInfo Package            
                    hubContext.Clients.All.updateIncidentStatusAdmin(new IncidentInfo(updateIncident));
                    Services.Log.Info("Connected Clients Updated");

                    break;
            }
        }
        public static void RevokeProviderJobs(Incident updateIncident, ApiServices Services)
        {
            IHubContext hubContext = Services.GetRealtime<IncidentHub>();

            hubContext.Clients.All.revokeMobileProviderClientJob(updateIncident.Id);
            Services.Log.Info("All Mobile Providers Offered Job");
        }
        public static void ProcessProviderOutreach(Incident newIncident, ApiServices Services)
        {
            IHubContext hubContext = Services.GetRealtime<IncidentHub>();

            ProviderJobOffer jobOffer = new ProviderJobOffer()
            {
                JobTag = newIncident.Id,
                ExpirySeconds = 30,
                IncidentInformation = new IncidentInfo(newIncident)
            };

            hubContext.Clients.All.offerMobileProviderClientJob(jobOffer);
            Services.Log.Info("All Mobile Providers Offered Job");
        }
        public async Task<HttpResponseMessage> CustomerNewIncident(IncidentRequest incidentRequest)
        {
            Services.Log.Info("New Incident Request [API]");

            // Get the logged-in user.
            var currentUser = this.User as ServiceUser;

            double locationX = 0;
            double locationY = 0;

            //Check Provided Location JObject & Process Accordingly
            if (incidentRequest.Location != null)
            {

                if (incidentRequest.Location.X != -1 && incidentRequest.Location.Y != -1)
                {
                    //Coordinates Flow - X & Y Coordinate Passed
                    locationX = incidentRequest.Location.X;
                    locationY = incidentRequest.Location.Y;
                }
                else
                {
                    //No Coordinates
                    //Consider Geocoding
                }
            }
            else
            {
                //No Location Flow - No Location JObject
            }

            Incident newIncident = new Incident()
            {
                Id = Guid.NewGuid().ToString(),
                JobCode = incidentRequest.JobCode,
                LocationObj = await JsonConvert.SerializeObjectAsync(incidentRequest.Location),
                CoordinateX = locationX,
                CoordinateY = locationY,
                ProviderUserID = currentUser.Id,
                VehicleGUID = incidentRequest.VehicleGUID,
                AdditionalDetails = incidentRequest.AdditionalDetails,
                StatusCode = "SUBMITTED", // Set the Initial Status
                StatusCustomerConfirm = true,
                StatusProviderConfirm = false,
                ServiceFee = (incidentRequest.ServiceFee != 0 || incidentRequest.ServiceFee != null) ? incidentRequest.ServiceFee : 0
            };

            stranddContext context = new stranddContext();
            context.Incidents.Add(newIncident);

            await context.SaveChangesAsync();
            Services.Log.Info("New Incident Created [" + newIncident.Id + "]");

            IncidentRequestResponse returnObject = new IncidentRequestResponse { IncidentGUID = newIncident.Id };
            string responseText = JsonConvert.SerializeObject(returnObject);

            //Notifying Connect WebClients with IncidentInfo Package
            IHubContext hubContext = Services.GetRealtime<IncidentHub>();
            hubContext.Clients.All.saveNewIncidentCustomer(new IncidentInfo(newIncident));
            ProcessProviderOutreach(newIncident, Services);

            Services.Log.Info("Connected Clients Updated");

            SendGridController.SendIncidentSubmissionAdminEmail(newIncident, Services);

            await HistoryEvent.logHistoryEventAsync("INCIDENT_NEW_CUSTOMER", null, newIncident.Id, null, currentUser.Id, null);

            return this.Request.CreateResponse(HttpStatusCode.Created, responseText);
        }
        public IncidentInfo(Incident baseIncident)
        {
            //Create UserInfo Object based upon Passed in ProviderUserID [Call to DB Made in Constructor]
            AccountInfo lookupUser = new AccountInfo(baseIncident.ProviderUserID);

            //Create VehicleInfo Object based upon Passed in VehicleGUID [Call to DB Made in Constructor]
            VehicleInfo lookupVehicle = new VehicleInfo(baseIncident.VehicleGUID);

            stranddContext context = new stranddContext();

            IncidentCosting lookupIncidentCosting = context.IncidentCostings
                                                    .Where(u => u.IncidentGUID == baseIncident.Id)
                                                    .Where(v => v.Type == "CUSTOMER")
                                                    .FirstOrDefault();

            //Payment Information
            List <Payment> lookupPaymentList = context.Payments
                                               .Where(u => u.IncidentGUID == baseIncident.Id)
                                               .ToList <Payment>();

            string paymentMethodString = null;

            if (lookupPaymentList.Count != 0)
            {
                if (lookupPaymentList.Count > 1)
                {
                    paymentMethodString = "Multiple Payments [" + lookupPaymentList.Count.ToString() + "]";
                }
                else
                {
                    paymentMethodString = lookupPaymentList[0].PaymentPlatform;
                }
            }

            decimal sumPaymentTotal = lookupPaymentList.Sum(a => a.Amount);

            //Confirmed Admin Information
            HistoryEvent lookupAdminEvent = context.HistoryLog
                                            .Where(u => u.ReferenceID == baseIncident.Id)
                                            .OrderByDescending(d => d.CreatedAt)
                                            .Where(v => v.Code == "INCIDENT_STATUS_ADMIN")
                                            .Where(x => x.Attribute == "CONFIRMED" || x.Attribute == "OPERATOR-ASSIGNED")
                                            .FirstOrDefault();

            AccountInfo lookupAdmin;

            if (lookupAdminEvent != null)
            {
                lookupAdmin = new AccountInfo(lookupAdminEvent.AdminID);
            }
            else
            {
                lookupAdmin = new AccountInfo(null);
            }

            this.IncidentGUID          = baseIncident.Id;
            this.IncidentUserInfo      = lookupUser;
            this.IncidentVehicleInfo   = lookupVehicle;
            this.ConfirmedAdminAccount = lookupAdmin;
            this.JobCode             = baseIncident.JobCode;
            this.LocationObj         = (baseIncident.LocationObj != null) ? JsonConvert.DeserializeObject <IncidentLocation>(baseIncident.LocationObj) : null;
            this.ConcertoCaseID      = baseIncident.ConcertoCaseID;
            this.StatusCode          = baseIncident.StatusCode;
            this.Rating              = baseIncident.Rating;
            this.ServiceFee          = baseIncident.ServiceFee;
            this.CoordinateX         = baseIncident.CoordinateX;
            this.CoordinateY         = baseIncident.CoordinateY;
            this.ProviderArrivalTime = baseIncident.ProviderArrivalTime;
            this.CreatedAt           = baseIncident.CreatedAt;
            this.UpdatedAt           = baseIncident.UpdatedAt;
            this.CustomerComments    = baseIncident.CustomerComments;
            this.StaffNotes          = baseIncident.StaffNotes;
            this.PaymentAmount       = sumPaymentTotal;     //(lookupPayment != null) ? lookupPayment.Amount : 0;
            this.PaymentMethod       = paymentMethodString; //(lookupPayment != null) ? lookupPayment.PaymentPlatform : null;
            this.AdditionalDetails   = baseIncident.AdditionalDetails;

            //retrive data IncidentCostings
            this.ServiceType               = (lookupIncidentCosting != null) ? lookupIncidentCosting.ServiceType   : null;
            this.ServiceKilometers         = (lookupIncidentCosting != null) ? lookupIncidentCosting.ServiceKilometers : 0;
            this.CalculatedBaseServiceCost = (lookupIncidentCosting != null) ? lookupIncidentCosting.CalculatedBaseServiceCost : 0;
            this.ParkingCosts              = (lookupIncidentCosting != null) ? lookupIncidentCosting.ParkingCosts : 0;
            this.TollCosts           = (lookupIncidentCosting != null) ? lookupIncidentCosting.TollCosts : 0;
            this.OtherCosts          = (lookupIncidentCosting != null) ? lookupIncidentCosting.OtherCosts : 0;
            this.OffsetDiscount      = (lookupIncidentCosting != null) ? lookupIncidentCosting.OffsetDiscount : 0;
            this.CalculatedSubtotal  = (lookupIncidentCosting != null) ? lookupIncidentCosting.CalculatedSubtotal : 0;
            this.TaxZoneRate         = (lookupIncidentCosting != null) ? lookupIncidentCosting.TaxZoneRate : 0;
            this.CalculatedTaxes     = (lookupIncidentCosting != null) ? lookupIncidentCosting.CalculatedTaxes : 0;
            this.CalculatedTotalCost = (lookupIncidentCosting != null) ? lookupIncidentCosting.CalculatedTotalCost : 0;
        }
        public IncidentInfo(Incident baseIncident)
        {
            //Create UserInfo Object based upon Passed in ProviderUserID [Call to DB Made in Constructor]
            AccountInfo lookupUser = new AccountInfo(baseIncident.ProviderUserID);

            //Create VehicleInfo Object based upon Passed in VehicleGUID [Call to DB Made in Constructor]
            VehicleInfo lookupVehicle = new VehicleInfo(baseIncident.VehicleGUID);

            stranddContext context = new stranddContext();

            IncidentCosting lookupIncidentCosting = context.IncidentCostings
              .Where(u => u.IncidentGUID == baseIncident.Id)
              .Where(v => v.Type == "CUSTOMER")
              .FirstOrDefault();

            //Payment Information
            List<Payment> lookupPaymentList = context.Payments
                .Where(u => u.IncidentGUID == baseIncident.Id)
                .ToList<Payment>();

            string paymentMethodString = null;

            if (lookupPaymentList.Count != 0)
            {
                if (lookupPaymentList.Count > 1) { paymentMethodString = "Multiple Payments [" + lookupPaymentList.Count.ToString() + "]"; }
                else { paymentMethodString = lookupPaymentList[0].PaymentPlatform; }
            }

            decimal sumPaymentTotal = lookupPaymentList.Sum(a => a.Amount);

            //Confirmed Admin Information
            HistoryEvent lookupAdminEvent = context.HistoryLog
                .Where(u => u.ReferenceID == baseIncident.Id)
                .OrderByDescending(d => d.CreatedAt)
                .Where(v => v.Code == "INCIDENT_STATUS_ADMIN")
                .Where(x => x.Attribute == "CONFIRMED" || x.Attribute == "OPERATOR-ASSIGNED")
                .FirstOrDefault();

            AccountInfo lookupAdmin;

            if (lookupAdminEvent != null) { lookupAdmin = new AccountInfo(lookupAdminEvent.AdminID); }
            else { lookupAdmin = new AccountInfo(null); }

            this.IncidentGUID = baseIncident.Id;
            this.IncidentUserInfo = lookupUser;
            this.IncidentVehicleInfo = lookupVehicle;
            this.ConfirmedAdminAccount = lookupAdmin;
            this.JobCode = baseIncident.JobCode;
            this.LocationObj = (baseIncident.LocationObj != null) ? JsonConvert.DeserializeObject<IncidentLocation>(baseIncident.LocationObj) : null;
            this.ConcertoCaseID = baseIncident.ConcertoCaseID;
            this.StatusCode = baseIncident.StatusCode;
            this.Rating = baseIncident.Rating;
            this.ServiceFee = baseIncident.ServiceFee;
            this.CoordinateX = baseIncident.CoordinateX;
            this.CoordinateY = baseIncident.CoordinateY;
            this.ProviderArrivalTime = baseIncident.ProviderArrivalTime;
            this.CreatedAt = baseIncident.CreatedAt;
            this.UpdatedAt = baseIncident.UpdatedAt;
            this.CustomerComments = baseIncident.CustomerComments;
            this.StaffNotes = baseIncident.StaffNotes;
            this.PaymentAmount = sumPaymentTotal; //(lookupPayment != null) ? lookupPayment.Amount : 0;
            this.PaymentMethod = paymentMethodString; //(lookupPayment != null) ? lookupPayment.PaymentPlatform : null;
            this.AdditionalDetails = baseIncident.AdditionalDetails;

            //retrive data IncidentCostings
            this.ServiceType = (lookupIncidentCosting != null) ? lookupIncidentCosting.ServiceType   : null;
            this.ServiceKilometers = (lookupIncidentCosting != null) ? lookupIncidentCosting.ServiceKilometers : 0;
            this.CalculatedBaseServiceCost = (lookupIncidentCosting != null) ? lookupIncidentCosting.CalculatedBaseServiceCost : 0;
            this.ParkingCosts = (lookupIncidentCosting != null) ? lookupIncidentCosting.ParkingCosts : 0;
            this.TollCosts = (lookupIncidentCosting != null) ? lookupIncidentCosting.TollCosts : 0;
            this.OtherCosts = (lookupIncidentCosting != null) ? lookupIncidentCosting.OtherCosts : 0;
            this.OffsetDiscount = (lookupIncidentCosting != null) ? lookupIncidentCosting.OffsetDiscount : 0;
            this.CalculatedSubtotal = (lookupIncidentCosting != null) ? lookupIncidentCosting.CalculatedSubtotal : 0;
            this.TaxZoneRate = (lookupIncidentCosting != null) ? lookupIncidentCosting.TaxZoneRate : 0;
            this.CalculatedTaxes = (lookupIncidentCosting != null) ? lookupIncidentCosting.CalculatedTaxes : 0;
            this.CalculatedTotalCost = (lookupIncidentCosting != null) ? lookupIncidentCosting.CalculatedTotalCost : 0;
        }
        public static void SendIncidentSubmissionAdminEmail(Incident incident, ApiServices Services)
        {
            SendGridMessage submissionMessage = new SendGridMessage();
            IncidentInfo submisionIncident = new IncidentInfo(incident);

            submissionMessage.From = SendGridHelper.GetAppFrom();
            submissionMessage.AddTo(WebConfigurationManager.AppSettings["RZ_SysAdminEmail"]);
            submissionMessage.Html = " ";
            submissionMessage.Text = " ";
            submissionMessage.Subject = " [" + WebConfigurationManager.AppSettings["MS_MobileServiceName"] + "]";

            submissionMessage.EnableTemplateEngine(WebConfigurationManager.AppSettings["RZ_SubmisionTemplateID"]);
            submissionMessage.AddSubstitution("%timestamp%", new List<string> { submisionIncident.CreatedAt.ToString() });
            submissionMessage.AddSubstitution("%incidentguid%", new List<string> { submisionIncident.IncidentGUID });
            submissionMessage.AddSubstitution("%vehicledetails%", new List<string> { submisionIncident.IncidentVehicleInfo.RegistrationNumber });
            submissionMessage.AddSubstitution("%name%", new List<string> { submisionIncident.IncidentUserInfo.Name });
            submissionMessage.AddSubstitution("%phone%", new List<string> { submisionIncident.IncidentUserInfo.Phone });
            submissionMessage.AddSubstitution("%email%", new List<string> { submisionIncident.IncidentUserInfo.Email });
            submissionMessage.AddSubstitution("%jobdescription%", new List<string> { submisionIncident.JobCode });
            submissionMessage.AddSubstitution("%location%", new List<string> { submisionIncident.LocationObj.RGDisplay });

            // Create an Web transport for sending email.
            var transportWeb = new Web(SendGridHelper.GetNetCreds());

            // Send the email.
            try
            {
                transportWeb.Deliver(submissionMessage);
                Services.Log.Info("New Incident Submission Email Sent to [" + submisionIncident.IncidentUserInfo.Email + "]");
            }
            catch (InvalidApiRequestException ex)
            {
                for (int i = 0; i < ex.Errors.Length; i++)
                {
                    Services.Log.Error(ex.Errors[i]);
                }
            }
        }