Пример #1
0
        internal static List <EfParaquickMessage> FindNextMessageSet(DbContext db, EfParaquickSession efSession)
        {
            //Find the next messageset sequence for this session (we go by ResponseDate) - can be null
            long?messageSetSequence = efSession.ParaquickMessages.Where(m => m.ResponseDate == null).OrderBy(m => m.MessageSetSequence).ThenBy(m => m.MessageSequence).FirstOrDefault()?.MessageSetSequence;

            //get the messages for the set - can be empty list
            var efMessages = efSession.ParaquickMessages.Where(m => m.MessageSetSequence == messageSetSequence).OrderBy(m => m.MessageSetSequence).ThenBy(m => m.MessageSequence).ToList();


            //OLD

            //Find the next messageset sequence for this session (we go by ResponseDate) - can be null
            //var xmessageSetSequence= (from msg in db.ParaquickMessages where msg.SessionId == efSession.Id && msg.ResponseDate==null orderby msg.MessageSetSequence, msg.MessageSequence select msg.MessageSetSequence).First();

            //get the messages for the set - can be empty list
            //var efMessages=(from msg in db.ParaquickMessages where msg.MessageSetSequence==messageSetSequence orderby msg.MessageSetSequence, msg.MessageSequence select msg).ToList();

            //verify that the set has not been partially processed for some reason
            foreach (var efMessage in efMessages)
            {
                if (efMessage.ResponseDate != null && efMessage.ResponseXml != null && efMessage.StatusCode != null)
                {
                    return(null);
                }
            }

            return(efMessages);
        }
Пример #2
0
        protected override string OnGetLastError(string ticket)
        {
            string message;

            if (ticket == ServiceUtils.ZeroTicket)
            {
                //note: we should never see the zero tickets, but we report it here
                message = "Can't process zero ticket";
                Error(message);
            }
            else
            {
                using (var db = ServiceUtils.CreateDbContext())
                {
                    EfParaquickSession efSession = ServiceUtils.FindSession(db, ticket);

                    if (efSession != null)
                    {
                        //return response-level and ticket-level errors
                        //(no need to log them again)
                        message = OnGetLastError(db, efSession);
                    }
                    else
                    {
                        //we report bad tickets here
                        message = $"can't find ticket ({ticket})";
                        Error(message);
                    }
                }
            }


            return(message);
        }
Пример #3
0
        internal static void Close(DbContext db, EfParaquickSession efSession)
        {
            //change status to success or error based on session errors and response status codes

            if (efSession.ParaquickMessages.Where(m => m.StatusCode == null).Count() > 0)
            {
                efSession.StatusId = (long)SessionStatuses.Incomplete;
            }
            else if (efSession.ParaquickSessionErrors.Count > 0)
            {
                efSession.StatusId = (long)SessionStatuses.Error;
            }
            else if (efSession.ParaquickMessages.Where(m => m.StatusCode != "0").Count() > 0)
            {
                efSession.StatusId = (long)SessionStatuses.Error;
            }
            else
            {
                efSession.StatusId = (long)SessionStatuses.Success;
            }

            efSession.EndDate = DateTime.Now;

            TruncateSession(efSession);

            db.SaveChanges();
        }
Пример #4
0
        internal static int CalculatePercentComplete(DbContext db, EfParaquickSession efSession)
        {
            int complete = efSession.ParaquickMessages.Where(m => m.ResponseDate != null).ToList().Count;
            int total    = efSession.ParaquickMessages.Count;
            int pctComplete;

            if (complete == total)
            {
                pctComplete = 100;
            }
            else
            {
                var fPc = ((float)complete) / total;
                pctComplete = (int)(fPc * 100);

                //excessive but certain
                if (pctComplete <= 0)
                {
                    pctComplete = 1;
                }

                //excessive but certain
                if (pctComplete >= 100)
                {
                    pctComplete = 99;
                }
            }

            return(pctComplete);
        }
Пример #5
0
 protected virtual bool OnRetryConnection(DbContext db, EfParaquickSession efSession, HResult hResult, out string companyFilePath)
 {
     //default behavior is to not retry
     //but implmentations may want to instruct the webconnector to try again, optionally with another file
     companyFilePath = null;
     return(false);
 }
Пример #6
0
        public void Save()
        {
            using (var db = ServiceUtils.CreateDbContext())
            {
                EfParaquickSession efSession = new EfParaquickSession();
                efSession.CompanyId  = CompanyId;
                efSession.Ticket     = Ticket;
                efSession.CreateDate = CreateDate;
                efSession.StatusId   = (long)SessionStatuses.New;

                ServiceUtils.TruncateSession(efSession);

                db.ParaquickSessions.Add(efSession);

                //add  requests
                foreach (var msgSet in _messageSets.OrderBy(ms => ms.Sequence))
                {
                    foreach (var msg in msgSet.Messages.OrderBy(r => r.Sequence))
                    {
                        if (msg.RqMsg != null)
                        {
                            string rqTypeName    = msg.RqMsg.GetType().Name;
                            var    efMessageType = (from mt in db.ParaquickMessageTypes where mt.RequestTypeName == rqTypeName select mt).FirstOrDefault();

                            if (efMessageType != null)
                            {
                                EfParaquickMessage efMessage = new EfParaquickMessage();
                                efMessage.Session             = efSession;
                                efMessage.MessageSetSequence  = msgSet.Sequence;
                                efMessage.MessageSequence     = msg.Sequence;
                                efMessage.ApplicationEntityId = msg.ApplicationEntityId;
                                efMessage.RequestId           = msg.RequestId;
                                efMessage.RequestDate         = msg.RequestDate;
                                efMessage.MessageType         = efMessageType;
                                efMessage.RequestXml          = msg.RqMsg.Serialize();

                                ServiceUtils.TruncateMessage(efMessage);

                                db.ParaquickMessages.Add(efMessage);
                            }
                            else
                            {
                                throw new InvalidOperationException($"RqMsg type not found ({rqTypeName})");
                            }
                        }
                        else
                        {
                            throw new InvalidOperationException("RqMsg must have a value");
                        }
                    }
                }


                db.SaveChanges();

                //refresh stuff
                Id = efSession.Id;
                LoadMessageSets(db, efSession);
            }
        }
Пример #7
0
        internal static void Open(DbContext db, EfParaquickSession efSession)
        {
            efSession.StatusId  = (long)SessionStatuses.Open;
            efSession.StartDate = DateTime.Now;

            TruncateSession(efSession);

            db.SaveChanges();
        }
Пример #8
0
        internal static void Reset(DbContext db, EfParaquickSession efSession)
        {
            efSession.StatusId  = (long)SessionStatuses.New;
            efSession.StartDate = null;

            TruncateSession(efSession);

            db.SaveChanges();
        }
Пример #9
0
        internal static void Session(DbContext db, EfParaquickSession efSession, string hcpXml, string qbCountry, int?qbMajorVersion, int?qbMinorVersion)
        {
            efSession.Company.HcpXml  = hcpXml;
            efSession.Company.Country = qbCountry;
            efSession.Company.Major   = qbMajorVersion;
            efSession.Company.Minor   = qbMinorVersion;

            TruncateSession(efSession);

            db.SaveChanges();
        }
Пример #10
0
        protected virtual string OnGetCloseMessage(DbContext db, EfParaquickSession efSession)
        {
            //TODO StopOnErrors? if we didn't stop on errors, do we notify user that errors occured?
            string message = $"Session closed.";

            if (efSession.StatusId == (int)SessionStatuses.Error)
            {
                message += " Errors occurred.";
            }

            return(message);
        }
Пример #11
0
        internal static void SessionError(DbContext db, EfParaquickSession efSession, string message)
        {
            EfParaquickSessionError sessionError = new EfParaquickSessionError();

            sessionError.Session = efSession;
            sessionError.Date    = DateTime.Now;
            sessionError.Message = message;

            TruncateSessionError(sessionError);

            db.ParaquickSessionErrors.Add(sessionError);

            db.SaveChanges();
        }
Пример #12
0
        protected override string OnAuthenticate(string username, string password, out AuthCodes authCode, out AuthOptions authOptions)
        {
            using (var db = ServiceUtils.CreateDbContext())
            {
                //Find the company based on the unique user name
                EfParaquickCompany efCompany = (from c in db.ParaquickCompanies where c.UserName == username && c.Password == password select c).FirstOrDefault();

                if (efCompany != null)
                {
                    authOptions = new AuthOptions();

                    EfParaquickSession efSession = ServiceUtils.FindNextSession(db, efCompany.Id);

                    //work to do?
                    if (efSession != null)
                    {
                        //allow implementors to override
                        authCode = OnNewSession(db, efSession, authOptions);

                        if (authCode == AuthCodes.VALID)
                        {
                            //open and return ticket
                            ServiceUtils.Open(db, efSession);
                            return(efSession.Ticket);
                        }
                        else
                        {
                            //implementors can override the code and the options
                            //but not the session record or the ticket
                            return(ServiceUtils.ZeroTicket);
                        }
                    }
                    else
                    {
                        //nothing to do
                        authCode = AuthCodes.NONE;
                    }
                }
                else
                {
                    //bad credentials
                    Error($"Incorrect username or password for user ({username})");
                    authCode = AuthCodes.NVU;
                }


                authOptions = null;
                return(ServiceUtils.ZeroTicket);
            }
        }
Пример #13
0
        protected void LoadMessageSets(DbContext db, EfParaquickSession efSession)
        {
            _messageSets.Clear();

            var efMessages = (from m in db.ParaquickMessages where m.SessionId == efSession.Id orderby m.MessageSetSequence, m.MessageSequence select m).ToList();

            MessageSet messageSet = null;

            foreach (var efMessage in efMessages)
            {
                if (efMessage.MessageSetSequence != messageSet?.Sequence)
                {
                    messageSet = new MessageSet(efMessage);
                    _messageSets.Add(messageSet);
                }

                messageSet.AddMessage(efMessage);
            }
        }
Пример #14
0
        public static string FormatErrors(EfParaquickSession efSession)
        {
            //format response-level and ticket-level errors

            string message = "Errors occurred.";

            foreach (var se in efSession.ParaquickSessionErrors)
            {
                message += $" [Session ({se.SessionId}) : {se.Message}]";
            }

            foreach (var msg in efSession.ParaquickMessages)
            {
                if (msg.StatusCode != "0")
                {
                    message += $" [Request ({msg.Id}) : {msg.StatusCode} - {msg.StatusMessage}]";
                }
            }

            return(message);
        }
Пример #15
0
        protected override string OnConnectionError(string ticket, HResult hResult)
        {
            if (ticket != ServiceUtils.ZeroTicket)
            {
                using (var db = ServiceUtils.CreateDbContext())
                {
                    EfParaquickSession efSession = ServiceUtils.FindSession(db, ticket);

                    if (efSession != null)
                    {
                        //log this error
                        SessionError(db, efSession, hResult.Format());

                        //ask the implementation if we should tell the WC to retry
                        string companyFilePath;
                        if (OnRetryConnection(db, efSession, hResult, out companyFilePath))
                        {
                            return(companyFilePath);
                        }
                        else
                        {
                            //if not, we reset the session to "New" and let the user fix it and try again
                            ServiceUtils.Reset(db, efSession);
                        }
                    }
                    else
                    {
                        //note: getLastError will not be called so we log this here
                        Error("Can't find ticket ({ticket}) during connection error");
                    }
                }
            }
            else
            {
                //note: getLastError will not be called so we log this here
                Error("Can't process zeroticket during connection error");
            }

            return("done");
        }
Пример #16
0
        protected override string OnCloseConnection(string ticket)
        {
            //note: we should never see the zero ticket here either
            //      but it's already been logged at this point
            if (ticket != ServiceUtils.ZeroTicket)
            {
                using (var db = ServiceUtils.CreateDbContext())
                {
                    EfParaquickSession efSession = ServiceUtils.FindSession(db, ticket);

                    //bad tickets have already been logged
                    if (efSession != null)
                    {
                        //close session
                        ServiceUtils.Close(db, efSession);

                        //allow implementation to send custom message back to WC
                        return(OnGetCloseMessage(db, efSession));
                    }
                }
            }

            return($"Session closed for invalid ticket {ticket}");
        }
Пример #17
0
 protected virtual void OnSessionError(DbContext db, EfParaquickSession efSession, string errorMessage)
 {
 }
Пример #18
0
 protected virtual AuthCodes OnNewSession(DbContext db, EfParaquickSession efSession, AuthOptions authOptions)
 {
     //the default behavior is to require the company file to be open ("") with no other options specified
     //but implmentations may want to do something different
     return(AuthCodes.VALID);
 }
Пример #19
0
 protected void ResponseError(DbContext db, EfParaquickSession efSession, EfParaquickMessage efMessage, string errorMessage)
 {
     //error message is already in messages table
     OnResponseError(db, efSession, efMessage, errorMessage);
 }
Пример #20
0
 protected virtual void OnResponseError(DbContext db, EfParaquickSession efSession, EfParaquickMessage efMessage, string errorMessage)
 {
 }
Пример #21
0
 public static void TruncateSession(EfParaquickSession efSession)
 {
     DataAnnotations.ObjectTruncator.Truncate(efSession);
     DataAnnotations.ObjectTruncator.Truncate(efSession.Company);
 }
Пример #22
0
 protected void RequestError(DbContext db, EfParaquickSession efSession, EfParaquickMessage efMessage, string errorMessage)
 {
     ServiceUtils.RequestError(db, efMessage, errorMessage);
     OnRequestError(db, efSession, efMessage, errorMessage);
 }
Пример #23
0
 protected virtual string OnGetLastError(DbContext db, EfParaquickSession efSession)
 {
     return(ServiceUtils.FormatErrors(efSession));
 }
Пример #24
0
        protected override string OnCreateRequestMessage(string ticket, string hcpXml, string companyFilePath, string qbCountry, int qbMajorVersion, int qbMinorVersion)
        {
            //zerotickets should never be seen here, but if so, they will recur in getLastError and be logged there
            if (ticket != ServiceUtils.ZeroTicket)
            {
                using (var db = ServiceUtils.CreateDbContext())
                {
                    EfParaquickSession efSession = ServiceUtils.FindSession(db, ticket);

                    //bad tickets will recur in getLastError and be logged there
                    if (efSession != null)
                    {
                        //confirm file path
                        if (IsCompanyFileValid(db, efSession, companyFilePath))
                        {
                            //save the hcpXml & other information in the company record
                            if (!string.IsNullOrEmpty(hcpXml))
                            {
                                ServiceUtils.Session(db, efSession, hcpXml, qbCountry, qbMajorVersion, qbMinorVersion);
                            }

                            //find next message for this ticket
                            List <EfParaquickMessage> efMessages = ServiceUtils.FindNextMessageSet(db, efSession);

                            if (efMessages != null)
                            {
                                //TODO do we set OnError to stopOnErrors in the request?
                                RqMsgSet rqMsgSet = new RqMsgSet();

                                foreach (var efMessage in efMessages)
                                {
                                    //deserialize request message
                                    IRqMsg rqMsg = (IRqMsg)Msg.Deserialize(efMessage.MessageType.RequestTypeName, efMessage.RequestXml);

                                    //allow implementation to see/modify message
                                    string errorMessage = OnRequest(db, efMessage, rqMsg);
                                    if (errorMessage == null)
                                    {
                                        //add it to message set
                                        rqMsgSet.Add(rqMsg);
                                    }
                                    else
                                    {
                                        //"close" this request, don't send to WC
                                        RequestError(db, efSession, efMessage, errorMessage);
                                    }
                                }

                                //TODO is "nothing to do" at this point an error?

                                //send it
                                string xml = rqMsgSet.Serialize();
                                return(xml);
                            }
                            else
                            {
                                //something wrong with the message set in the database, log it
                                SessionError(db, efSession, $"An error occurred when building the message set for session ({efSession.Id})");

                                //this is pretty bad, let's just close the session
                                ServiceUtils.Close(db, efSession);
                            }
                        }
                        else
                        {
                            //log error
                            SessionError(db, efSession, $"Incorrect company file ({companyFilePath}) for company ({efSession.CompanyId})");
                        }
                    }
                }
            }

            //error condition
            return("");
        }
Пример #25
0
 protected void SessionError(DbContext db, EfParaquickSession efSession, string errorMessage)
 {
     ServiceUtils.SessionError(db, efSession, errorMessage);
     OnSessionError(db, efSession, errorMessage);
 }
Пример #26
0
        protected override int OnResponseMessage(string ticket, string responseXml, HResult hResult)
        {
            //zerotickets should never be seen here, but if so, they will recur in getLastError and be logged there
            if (ticket != ServiceUtils.ZeroTicket)
            {
                using (var db = ServiceUtils.CreateDbContext())
                {
                    EfParaquickSession efSession = ServiceUtils.FindSession(db, ticket);

                    //bad tickets will recur in getLastError and be logged there
                    if (efSession != null)
                    {
                        //COM error?
                        if (hResult == null)
                        {
                            //deserialize response and process success/error
                            RsMsgSet rsMsgSet = new RsMsgSet();
                            QBXML    qbxml    = rsMsgSet.Deserialize(responseXml);

                            //TODO update paraquick entities based on response type
                            foreach (var rsMsg in rsMsgSet)
                            {
                                var efMessage = efSession.ParaquickMessages.Where(m => m.RequestId == rsMsg.requestID).FirstOrDefault();

                                if (efMessage != null)
                                {
                                    ServiceUtils.Response(db, efMessage, rsMsg);

                                    //allow implementor to do something with response
                                    OnResponse(db, efMessage, rsMsg);

                                    if (rsMsg.statusCode != "0")
                                    {
                                        //TODO stop on errors?
                                        ResponseError(db, efSession, efMessage, rsMsg.statusMessage);
                                    }
                                }
                                else
                                {
                                    //TODO stop on errors?
                                    SessionError(db, efSession, $"Can't find request ({rsMsg.requestID})");
                                }
                            }


                            //TODO StopOnErrors? do we stop on errors here (return -1) or keep going?
                            //report "%" - completed messages/total messages for session
                            int pctComplete = ServiceUtils.CalculatePercentComplete(db, efSession);
                            return(pctComplete);
                        }
                        else
                        {
                            SessionError(db, efSession, $"COM Error {hResult.Format()}");
                        }
                    }
                }
            }

            //error condition
            return(-1);
        }
Пример #27
0
 protected virtual bool IsCompanyFileValid(DbContext db, EfParaquickSession efSession, string companyFilePath)
 {
     //the default behavior is to always use the file that is currently open,
     //but implmentations may want to do something different
     return(true);
 }