Ejemplo n.º 1
0
        private static DateTime GetDateLimit(Permissions permType, long userGroupNum)
        {
            //No need to check RemotingRole; no call to db.
            DateTime nowDate = MiscData.GetNowDateTime().Date;
            DateTime retVal  = DateTime.MinValue;

            for (int i = 0; i < GroupPermissionC.List.Length; i++)
            {
                if (GroupPermissionC.List[i].UserGroupNum != userGroupNum || GroupPermissionC.List[i].PermType != permType)
                {
                    continue;
                }
                //this should only happen once.  One match.
                if (GroupPermissionC.List[i].NewerDate.Year > 1880)
                {
                    retVal = GroupPermissionC.List[i].NewerDate;
                }
                if (GroupPermissionC.List[i].NewerDays == 0)              //do not restrict by days
                //do not change retVal
                {
                }
                else if (nowDate.AddDays(-GroupPermissionC.List[i].NewerDays) > retVal)
                {
                    retVal = nowDate.AddDays(-GroupPermissionC.List[i].NewerDays);
                }
            }
            return(retVal);
        }
Ejemplo n.º 2
0
 ///<summary>Must be called after Preference cache has been filled.
 ///Deletes all signals older than 2 days if this has not been run within the last week.  Will fail silently if anything goes wrong.</summary>
 public static void ClearOldSignals()
 {
     if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
     {
         Meth.GetVoid(MethodBase.GetCurrentMethod());
         return;
     }
     try {
         if (Prefs.GetContainsKey(PrefName.SignalLastClearedDate.ToString()) &&
             PrefC.GetDateT(PrefName.SignalLastClearedDate) > MiscData.GetNowDateTime().AddDays(-7)) //Has already been run in the past week. This is all server based time.
         {
             return;                                                                                 //Do not run this process again.
         }
         string command = "";
         if (DataConnection.DBtype == DatabaseType.MySql)                                          //easier to read that using the DbHelper Functions and it also matches the ConvertDB3 script
         {
             command = "DELETE FROM signalod WHERE SigDateTime < DATE_ADD(NOW(),INTERVAL -2 DAY)"; //Itypes only older than 2 days
             Db.NonQ(command);
         }
         else                                                                           //oracle
         {
             command = "DELETE FROM signalod WHERE SigDateTime < CURRENT_TIMESTAMP -2"; //Itypes only older than 2 days
             Db.NonQ(command);
         }
         SigMessages.ClearOldSigMessages();                                            //Clear messaging buttons which use to be stored in the signal table.
         //SigElements.DeleteOrphaned();
         Prefs.UpdateDateT(PrefName.SignalLastClearedDate, MiscData.GetNowDateTime()); //Set Last cleared to now.
     }
     catch (Exception) {
         //fail silently
     }
 }
Ejemplo n.º 3
0
        ///<summary>Will throw an exception if already clocked in.</summary>
        public static void ClockIn(long employeeNum)
        {
            //we'll get this again, because it may have been a while and may be out of date
            ClockEvent clockEvent = ClockEvents.GetLastEvent(employeeNum);

            if (clockEvent == null)           //new employee clocking in
            {
                clockEvent             = new ClockEvent();
                clockEvent.EmployeeNum = employeeNum;
                clockEvent.ClockStatus = TimeClockStatus.Home;
                ClockEvents.Insert(clockEvent);                       //times handled
            }
            else if (clockEvent.ClockStatus == TimeClockStatus.Break) //only incomplete breaks will have been returned.
            //clocking back in from break
            {
                clockEvent.TimeEntered2   = MiscData.GetNowDateTime();
                clockEvent.TimeDisplayed2 = clockEvent.TimeEntered2;
                ClockEvents.Update(clockEvent);
            }
            else                                           //normal clock in/out
            {
                if (clockEvent.TimeDisplayed2.Year < 1880) //already clocked in
                {
                    throw new Exception(Lans.g("ClockEvents", "Error.  Already clocked in."));
                }
                else                  //clocked out for home or lunch.  Need to clock back in by starting a new row.
                {
                    TimeClockStatus tcs = clockEvent.ClockStatus;
                    clockEvent             = new ClockEvent();
                    clockEvent.EmployeeNum = employeeNum;
                    clockEvent.ClockStatus = tcs;
                    ClockEvents.Insert(clockEvent);                    //times handled
                }
            }
        }
Ejemplo n.º 4
0
        ///<summary>Creates historical entry of deletion into wikiPageHist, and deletes current non-draft page from WikiPage.
        ///For middle tier purposes we need to have the currently logged in user passed into this method.</summary>
        public static void Archive(string pageTitle, long userNumCur)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                Meth.GetVoid(MethodBase.GetCurrentMethod(), pageTitle, userNumCur);
                return;
            }
            WikiPage wikiPage = GetByTitle(pageTitle);

            if (wikiPage == null)
            {
                return;                //The wiki page could not be found by the page title, nothing to do.
            }
            WikiPageHist wikiPageHist = PageToHist(wikiPage);

            //preserve the existing page with user credentials
            WikiPageHists.Insert(wikiPageHist);
            //make entry to show who deleted the page
            wikiPageHist.IsDeleted     = true;
            wikiPageHist.UserNum       = userNumCur;
            wikiPageHist.DateTimeSaved = MiscData.GetNowDateTime();
            WikiPageHists.Insert(wikiPageHist);
            //Now mark the wikipage as IsDeleted
            wikiPage.IsDeleted     = true;
            wikiPage.DateTimeSaved = MiscData.GetNowDateTime();
            Crud.WikiPageCrud.Update(wikiPage);
            //Remove all associated home pages for all users.
            UserOdPrefs.DeleteForValueString(0, UserOdFkeyType.WikiHomePage, pageTitle);
        }
Ejemplo n.º 5
0
 ///<summary>Includes all attached fields.  Intelligently inserts, updates, or deletes old fields.</summary>
 ///<param name="isOldSheetDuplicate">True if the sheetDef being created is a copy of a custom sheet that has a DateTCreated of 0001-01-01.
 ///DateTCreated determines whether or not text fields will be shifted up 5 pixels when PDF is created from sheet to fix bug job B16020.</param>
 public static long InsertOrUpdate(SheetDef sheetDef, bool isOldSheetDuplicate = false)
 {
     if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
     {
         sheetDef.SheetDefNum = Meth.GetLong(MethodBase.GetCurrentMethod(), sheetDef, isOldSheetDuplicate);
         return(sheetDef.SheetDefNum);
     }
     if (sheetDef.IsNew)
     {
         if (!isOldSheetDuplicate)
         {
             sheetDef.DateTCreated = MiscData.GetNowDateTime();
         }
         sheetDef.SheetDefNum = Crud.SheetDefCrud.Insert(sheetDef);
     }
     else
     {
         Crud.SheetDefCrud.Update(sheetDef);
     }
     foreach (SheetFieldDef field in sheetDef.SheetFieldDefs)
     {
         field.SheetDefNum = sheetDef.SheetDefNum;
     }
     SheetFieldDefs.Sync(sheetDef.SheetFieldDefs, sheetDef.SheetDefNum);
     return(sheetDef.SheetDefNum);
 }
Ejemplo n.º 6
0
        ///<summary>The main logic that sends Podium invitations.  Set isService true only when the calling method is the Open Dental Service.</summary>
        public static void ThreadPodiumSendInvitations(bool isService)
        {
            long programNum = Programs.GetProgramNum(ProgramName.Podium);

            //Consider blocking re-entrance if this hasn't finished.
            //Only send invitations if the program link is enabled, the computer name is set to this computer, and eConnector is not set to send invitations
            if (!Programs.IsEnabled(ProgramName.Podium) ||
                !ODEnvironment.IdIsThisComputer(ProgramProperties.GetPropVal(programNum, PropertyDescs.ComputerNameOrIP)) ||
                ProgramProperties.GetPropVal(programNum, PropertyDescs.UseService) != POut.Bool(isService))
            {
                return;
            }
            //Keep a consistant "Now" timestamp throughout this method.
            DateTime nowDT = MiscData.GetNowDateTime();

            if (Podium.DateTimeLastRan == DateTime.MinValue)           //First time running the thread.
            {
                Podium.DateTimeLastRan = nowDT.AddMilliseconds(-PodiumThreadIntervalMS);
            }
            ReviewInvitationTrigger newPatTrigger      = PIn.Enum <ReviewInvitationTrigger>(ProgramProperties.GetPropVal(programNum, PropertyDescs.NewPatientTriggerType));
            ReviewInvitationTrigger existingPatTrigger = PIn.Enum <ReviewInvitationTrigger>(ProgramProperties.GetPropVal(programNum, PropertyDescs.ExistingPatientTriggerType));
            List <Appointment>      listNewPatAppts    = GetAppointmentsToSendReview(newPatTrigger, programNum, true);

            foreach (Appointment apptCur in listNewPatAppts)
            {
                Podium.SendData(Patients.GetPat(apptCur.PatNum), apptCur.ClinicNum);
            }
            List <Appointment> listExistingPatAppts = GetAppointmentsToSendReview(existingPatTrigger, programNum, false);

            foreach (Appointment apptCur in listExistingPatAppts)
            {
                Podium.SendData(Patients.GetPat(apptCur.PatNum), apptCur.ClinicNum);
            }
            Podium.DateTimeLastRan = nowDT;
        }
Ejemplo n.º 7
0
 ///<summary></summary>
 public static long Insert(Signalod sig)
 {
     if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
     {
         sig.SignalNum = Meth.GetLong(MethodBase.GetCurrentMethod(), sig);
         return(sig.SignalNum);
     }
     if (RemotingClient.RemotingRole == RemotingRole.ServerWeb)
     {
         //Refresh the cache now so that we don't have to refresh the cache when the clients update their cache.
         if (sig.IType == InvalidType.Fees && sig.FKeyType == KeyType.FeeSched && sig.FKey > 0)
         {
             //We don't want to refresh the entire feecache if we don't have to.
             Fees.InvalidateFeeSchedule(sig.FKey);
         }
         else
         {
             Cache.Refresh(sig.IType);
         }
     }
     //We need to explicitly get the server time in advance rather than using NOW(), because we need to update the signal object soon after creation.
     sig.SigDateTime = MiscData.GetNowDateTime();
     sig.RemoteRole  = RemotingClient.RemotingRole;
     return(Crud.SignalodCrud.Insert(sig));
 }
Ejemplo n.º 8
0
 ///<summary>Process all Signals and Acks Since a given DateTime.  Only to be used by OpenDentalWebService.  Returns latest valid signal Date/Time.  Can throw exception.</summary>
 public static void RefreshForWeb(ref DateTime sinceDateT)
 {
     //No need to check RemotingRole; no call to db.
     try {
         if (sinceDateT.Year < 1880)
         {
             sinceDateT = MiscData.GetNowDateTime();
         }
         //Get all invalid types since given time.
         List <int> itypes = Signalods.GetInvalidTypes(Signalods.RefreshTimed(sinceDateT));
         if (itypes.Count <= 0)
         {
             return;
         }
         string itypesStr = "";
         for (int i = 0; i < itypes.Count; i++)
         {
             if (i > 0)
             {
                 itypesStr += ",";
             }
             itypesStr += ((int)itypes[i]).ToString();
         }
         //Refresh the cache for the given invalid types.
         Cache.RefreshCache(itypesStr);
         sinceDateT = OpenDentBusiness.MiscData.GetNowDateTime();
     }
     catch (Exception e) {
         //Most likely cause for an exception here would be a thread collision between 2 consumers trying to refresh the cache at the exact same instant.
         //There is a chance that performing as subsequent refresh here would cause yet another collision but it's the best we can do without redesigning the entire cache pattern.
         Cache.Refresh(InvalidType.AllLocal);
         throw new Exception("Server cache may be invalid. Please try again. Error: " + e.Message);
     }
 }
Ejemplo n.º 9
0
        ///<summary>When user clicks on a colored light, they intend to ack it to turn it off.  This acks all signals with the specified index.  This is in case multiple signals have been created from different workstations.  This acks them all in one shot.  Must specify a time because you only want to ack signals earlier than the last time this workstation was refreshed.  A newer signal would not get acked.
        ///If this seems slow, then I will need to check to make sure all these tables are properly indexed.</summary>
        public static void AckButton(int buttonIndex, DateTime time)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                Meth.GetVoid(MethodBase.GetCurrentMethod(), buttonIndex, time);
                return;
            }
            //FIXME:UPDATE-MULTIPLE-TABLES

            /*string command= "UPDATE signalod,sigelement,sigelementdef "
             +"SET signalod.AckTime = ";
             *      if(FormChooseDatabase.DBtype==DatabaseType.Oracle) {
             *              command+="(SELECT CURRENT_TIMESTAMP FROM DUAL)";
             *      }else{//Assume MySQL
             *              command+="NOW()";
             *      }
             *      command+=" "
             +"WHERE signalod.AckTime < '1880-01-01' "
             +"AND SigDateTime <= '"+POut.PDateT(time)+"' "
             +"AND signalod.SignalNum=sigelement.SignalNum "
             +"AND sigelement.SigElementDefNum=sigelementdef.SigElementDefNum "
             +"AND sigelementdef.LightRow="+POut.PInt(buttonIndex);
             * Db.NonQ(command);*/
            //Rewritten so that the SQL is compatible with both Oracle and MySQL.
            string command = "SELECT signalod.SignalNum FROM signalod,sigelement,sigelementdef "
                             + "WHERE signalod.AckTime < " + POut.Date(new DateTime(1880, 1, 1), true) + " "
                             + "AND SigDateTime <= " + POut.DateT(time) + " "
                             + "AND signalod.SignalNum=sigelement.SignalNum "
                             + "AND sigelement.SigElementDefNum=sigelementdef.SigElementDefNum "
                             + "AND sigelementdef.LightRow=" + POut.Long(buttonIndex);
            DataTable table = Db.GetTable(command);

            if (table.Rows.Count == 0)
            {
                return;
            }
            command = "UPDATE signalod SET AckTime = ";
            if (DataConnection.DBtype == DatabaseType.Oracle)
            {
                command += POut.DateT(MiscData.GetNowDateTime());
            }
            else               //Assume MySQL
            {
                command += "NOW()";
            }
            command += " WHERE ";
            for (int i = 0; i < table.Rows.Count; i++)
            {
                command += "SignalNum=" + table.Rows[i][0].ToString();
                if (i < table.Rows.Count - 1)
                {
                    command += " OR ";
                }
            }
            Db.NonQ(command);
        }
Ejemplo n.º 10
0
 ///<summary>Acknowledge one sig message from the manage module grid.</summary>
 public static void AckSigMessage(SigMessage sigMessage)
 {
     if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
     {
         Meth.GetVoid(MethodBase.GetCurrentMethod(), sigMessage);
         return;
     }
     //To ack a message, simply update the AckDateTime on the original row.
     sigMessage.AckDateTime = MiscData.GetNowDateTime();
     Update(sigMessage);
 }
Ejemplo n.º 11
0
 ///<summary></summary>
 public static long Insert(Signalod sig)
 {
     if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
     {
         sig.SignalNum = Meth.GetLong(MethodBase.GetCurrentMethod(), sig);
         return(sig.SignalNum);
     }
     //we need to explicitly get the server time in advance rather than using NOW(),
     //because we need to update the signal object soon after creation.
     sig.SigDateTime = MiscData.GetNowDateTime();
     return(Crud.SignalodCrud.Insert(sig));
 }
Ejemplo n.º 12
0
        ///<summary>Also sets the DateSent to today.</summary>
        public static void SetCanadianClaimSent(long claimNum)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                Meth.GetVoid(MethodBase.GetCurrentMethod(), claimNum);
                return;
            }
            string command = "UPDATE claim SET ClaimStatus = 'S',"
                             + "DateSent= " + POut.Date(MiscData.GetNowDateTime())
                             + " WHERE ClaimNum = " + POut.Long(claimNum);

            Db.NonQ(command);
        }
Ejemplo n.º 13
0
 public static void WikiPageRestore(WikiPage wikiPageRestored, long userNum)
 {
     if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
     {
         Meth.GetVoid(MethodBase.GetCurrentMethod(), wikiPageRestored, userNum);
         return;
     }
     //Update the wikipage with new user and flip the IsDelete flag.
     wikiPageRestored.IsDeleted     = false;
     wikiPageRestored.UserNum       = userNum;
     wikiPageRestored.DateTimeSaved = MiscData.GetNowDateTime();
     Crud.WikiPageCrud.Update(wikiPageRestored);
 }
Ejemplo n.º 14
0
 ///<summary>Sets the necessary fields for the given responseWeb object.
 ///expDate should be in yyMM format.</summary>
 private static void HandleResponseSuccess(PayConnectResponseWeb responseWeb, string resStr, bool isPending)
 {
     if (isPending)
     {
         responseWeb.ProcessingStatus = PayConnectWebStatus.Pending;
         responseWeb.DateTimePending  = MiscData.GetNowDateTime();
     }
     else
     {
         responseWeb.ProcessingStatus  = PayConnectWebStatus.Completed;
         responseWeb.DateTimeCompleted = MiscData.GetNowDateTime();
     }
     responseWeb.LastResponseStr = resStr;
 }
Ejemplo n.º 15
0
        ///<summary>Table must include columns labeled LatestPayment and DateStart.</summary>
        public static void FilterRecurringChargeList(DataTable table)
        {
            DateTime curDate = MiscData.GetNowDateTime();

            //Loop through table and remove patients that do not need to be charged yet.
            for (int i = 0; i < table.Rows.Count; i++)
            {
                DateTime latestPayment = PIn.Date(table.Rows[i]["LatestPayment"].ToString());
                DateTime dateStart     = PIn.Date(table.Rows[i]["DateStart"].ToString());
                if (curDate > latestPayment.AddDays(31))               //if it's been more than a month since they made any sort of payment
                //if we reduce the days below 31, then slighly more people will be charged, especially from Feb to March.  31 eliminates those false positives.
                {
                    continue;                    //charge them
                }
                //Not enough days in the current month so show on the last day of the month
                //Example: DateStart=8/31/2010 and the current month is February 2011 which does not have 31 days.
                //So the patient needs to show in list if current day is the 28th (or last day of the month).
                int daysInMonth = DateTime.DaysInMonth(curDate.Year, curDate.Month);
                if (daysInMonth <= dateStart.Day && daysInMonth == curDate.Day && curDate.Date != latestPayment.Date) //if their recurring charge would fall on an invalid day of the month, and this is that last day of the month
                {
                    continue;                                                                                         //we want them to show because the charge should go in on this date.
                }
                if (curDate.Day >= dateStart.Day)                                                                     //If the recurring charge date was earlier in this month, then the recurring charge will go in for this month.
                {
                    if (curDate.Month > latestPayment.Month || curDate.Year > latestPayment.Year)                     //if the latest payment was last month (or earlier).  The year check catches December
                    {
                        continue;                                                                                     //No payments were made this month, so charge.
                    }
                }
                else                  //Else, current date is before the recurring date in the current month, so the recurring charge will be going in for last month
                                      //Check if payment didn't happen last month.
                {
                    if (curDate.AddMonths(-1).Date > latestPayment.Date &&              //the latest recurring charge payment for this card was before one month ago
                        curDate.AddMonths(-1).Month != latestPayment.Month)                         //the latest recurring charge payment for this card did not happen during last month
                    //&& curDate.Date!=latestPayment.Date)//no longer necessary since latest payment was before one month ago
                    {
                        //Charge did not happen last month so the patient needs to show up in list.
                        //Example: Last month had a recurring charge set at the end of the month that fell on a weekend.
                        //Today is the next month and still before the recurring charge date.
                        //This will allow the charge for the previous month to happen if the 30 day check didn't catch it above.
                        continue;
                    }
                }
                //Patient doesn't need to be charged yet so remove from the table.
                table.Rows.RemoveAt(i);
                i--;
            }
        }
Ejemplo n.º 16
0
 public static void HandleResponseError(PayConnectResponseWeb responseWeb, string resStr)
 {
     responseWeb.LastResponseStr = resStr;
     if (responseWeb.ProcessingStatus == PayConnectWebStatus.Created)
     {
         responseWeb.ProcessingStatus = PayConnectWebStatus.CreatedError;
     }
     else if (responseWeb.ProcessingStatus == PayConnectWebStatus.Pending)
     {
         responseWeb.ProcessingStatus = PayConnectWebStatus.PendingError;
     }
     else
     {
         responseWeb.ProcessingStatus = PayConnectWebStatus.UnknownError;
     }
     responseWeb.DateTimeLastError = MiscData.GetNowDateTime();
 }
Ejemplo n.º 17
0
        ///<summary>Creates a new perio exam for the given patient. Returns that perio exam. Handles setting default skipped teeth/implants. Does not create a security log entry.</summary>
        public static PerioExam CreateNewExam(Patient pat)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                return(Meth.GetObject <PerioExam>(MethodBase.GetCurrentMethod(), pat));
            }
            PerioExam newExam = new PerioExam {
                PatNum           = pat.PatNum,
                ExamDate         = DateTimeOD.Today,
                ProvNum          = pat.PriProv,
                DateTMeasureEdit = MiscData.GetNowDateTime()
            };

            Insert(newExam);
            PerioMeasures.SetSkipped(newExam.PerioExamNum, GetSkippedTeethForExam(pat, newExam));
            return(newExam);
        }
Ejemplo n.º 18
0
 ///<summary>Insertion logic that doesn't use the cache. Has special cases for generating random PK's and handling Oracle insertions.</summary>
 public static void SetInvalidNoCache(params InvalidType[] itypes)
 {
     if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
     {
         Meth.GetVoid(MethodBase.GetCurrentMethod(), itypes);
         return;
     }
     foreach (InvalidType iType in itypes)
     {
         Signalod sig = new Signalod();
         sig.IType       = iType;
         sig.DateViewing = DateTime.MinValue;
         sig.SigDateTime = MiscData.GetNowDateTime();
         sig.RemoteRole  = RemotingClient.RemotingRole;
         Crud.SignalodCrud.InsertNoCache(sig);
     }
 }
Ejemplo n.º 19
0
        ///<summary>Inserts a healthy heartbeat.</summary>
        public static void InsertHeartbeatForService(eServiceCode serviceCode)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                Meth.GetVoid(MethodBase.GetCurrentMethod(), serviceCode);
                return;
            }
            AlertItems.DeleteFor(AlertType.EConnectorDown);
            string command = "SELECT * FROM eservicesignal WHERE ServiceCode=" + POut.Int((int)serviceCode)
                             + " AND Severity IN ("
                             + POut.Int((int)eServiceSignalSeverity.NotEnabled) + ","
                             + POut.Int((int)eServiceSignalSeverity.Working) + ","
                             + POut.Int((int)eServiceSignalSeverity.Critical)
                             + ") ORDER BY SigDateTime DESC " + DbHelper.LimitWhere(1);//only select not enabled, working, and critical statuses.
            EServiceSignal eServiceSignalLast = Crud.EServiceSignalCrud.SelectOne(command);
            DateTime       dtNow = MiscData.GetNowDateTime();

            //If initializing or changing state to working from not working, insert two signals; An anchor and a rolling timestamp.
            if (eServiceSignalLast == null || eServiceSignalLast.Severity != eServiceSignalSeverity.Working)          //First ever heartbeat or critical which was not previously critical.
            {
                if (eServiceSignalLast != null && eServiceSignalLast.Severity == eServiceSignalSeverity.Critical
                    //Do not create a signal if the eConnector was stopped because of an update
                    && (eServiceSignalLast.SigDateTime > UpdateHistories.GetLastUpdateHistory().DateTimeUpdated ||
                        UpdateHistories.GetLastUpdateHistory().DateTimeUpdated.AddMinutes(10) < dtNow))
                {
                    //Changing from critical to working so alert user that this change took place and tell them how long we were in critical state.
                    //Insert() will also insert Alert.
                    Insert(new EServiceSignal()
                    {
                        ServiceCode = (int)serviceCode, Severity = eServiceSignalSeverity.Error, SigDateTime = dtNow, IsProcessed = false, Description = "Listener was critical for " + DateTime.Now.Subtract(eServiceSignalLast.SigDateTime).ToStringHmm()
                    });
                }
                Insert(new EServiceSignal()
                {
                    ServiceCode = (int)serviceCode, Severity = eServiceSignalSeverity.Working, SigDateTime = dtNow, IsProcessed = true, Description = "Heartbeat Anchor"
                });                                                                                                                                                                                     //anchor heartbeat
                Insert(new EServiceSignal()
                {
                    ServiceCode = (int)serviceCode, Severity = eServiceSignalSeverity.Working, SigDateTime = dtNow.AddSeconds(1), IsProcessed = true, Description = "Heartbeat"
                });                                                                                                                                                                                            //rolling heartbeat
                return;
            }
            eServiceSignalLast.SigDateTime = dtNow;
            Update(eServiceSignalLast);
        }
Ejemplo n.º 20
0
        ///<summary>Returns the Date that the user is restricted to for the passed-in permission.
        ///Returns MinVal if the user is not restricted or does not have the permission.</summary>
        public static DateTime GetDateRestrictedForPermission(Permissions permission, List <long> listUserGroupNums)
        {
            //No need to check RemotingRole; no call to db.
            DateTime        nowDate    = DateTime.MinValue;
            Func <DateTime> getNowDate = new Func <DateTime>(() => {
                if (nowDate.Year < 1880)
                {
                    nowDate = MiscData.GetNowDateTime().Date;
                }
                return(nowDate);
            });
            DateTime retVal = DateTime.MinValue;
            List <GroupPermission> listGroupPerms = GetForUserGroups(listUserGroupNums, permission);
            //get the permission that applies
            GroupPermission perm = listGroupPerms.OrderBy((GroupPermission y) => {
                if (y.NewerDays == 0 && y.NewerDate == DateTime.MinValue)
                {
                    return(DateTime.MinValue);
                }
                if (y.NewerDays == 0)
                {
                    return(y.NewerDate);
                }
                return(getNowDate().AddDays(-y.NewerDays));
            }).FirstOrDefault();

            if (perm == null)
            {
                //do not change retVal. The user does not have the permission.
            }
            else if (perm.NewerDate.Year < 1880 && perm.NewerDays == 0)
            {
                //do not change retVal. The user is not restricted by date.
            }
            else if (perm.NewerDate.Year > 1880)
            {
                retVal = perm.NewerDate;
            }
            else if (getNowDate().AddDays(-perm.NewerDays) > retVal)
            {
                retVal = getNowDate().AddDays(-perm.NewerDays);
            }
            return(retVal);
        }
Ejemplo n.º 21
0
        ///<summary>Returns the PK of the signal inserted if only one signal was passed in; Otherwise, returns 0.</summary>
        public static long Insert(params Signalod[] arraySignals)
        {
            if (arraySignals == null || arraySignals.Length < 1)
            {
                return(0);
            }
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                long signalNum = Meth.GetLong(MethodBase.GetCurrentMethod(), arraySignals);
                if (arraySignals.Length == 1)
                {
                    arraySignals[0].SignalNum = signalNum;
                }
                return(signalNum);
            }
            if (RemotingClient.RemotingRole == RemotingRole.ServerWeb)
            {
                //Make an in-memory list out of the array so that we can manipulate it without actually removing any entries passed in (for our insert below).
                List <Signalod> listSignals = arraySignals.ToList();
                //Refresh the cache now so that we don't have to refresh the cache when the clients update their cache.
                List <Signalod> listFeeSchedSignals = listSignals.Where(x => x.IType == InvalidType.Fees && x.FKeyType == KeyType.FeeSched && x.FKey > 0).ToList();
                foreach (Signalod signal in listFeeSchedSignals)
                {
                    Fees.InvalidateFeeSchedule(signal.FKey);
                }
                //Remove any signals from our list that we've already taken care of.
                listSignals.RemoveAll(x => x.IType == InvalidType.Fees && x.FKeyType == KeyType.FeeSched && x.FKey > 0);
                Cache.Refresh(listSignals.Select(x => x.IType).Distinct().ToArray());
            }
            //We need to explicitly get the server time in advance rather than using NOW(), because we need to update the signal object soon after creation.
            DateTime dateTimeNow = MiscData.GetNowDateTime();

            foreach (Signalod signal in arraySignals)
            {
                signal.SigDateTime = dateTimeNow;
                signal.RemoteRole  = RemotingClient.RemotingRole;
            }
            if (arraySignals.Length == 1)
            {
                return(Crud.SignalodCrud.Insert(arraySignals[0]));
            }
            Crud.SignalodCrud.InsertMany(arraySignals.ToList());
            return(0);
        }
Ejemplo n.º 22
0
        ///<summary>Inserts a signal for each operatory in the schedule that has been changed, and for the provider the schedule is for. This only
        ///inserts a signal for today's schedules. Generally should not be called outside of Schedules.cs</summary>
        public static void SetInvalidSched(params Schedule[] arraySchedules)
        {
            //No need to check RemotingRole; no call to db.
            //Per Nathan, we are only going to insert signals for today's schedules. Most workstations will not be looking at other days for extended
            //lengths of time.
            //Make an array of signals for every operatory involved.
            DateTime serverTime = MiscData.GetNowDateTime();

            Signalod[] arrayOpSignals = arraySchedules
                                        .Where(x => x.SchedDate.Date == DateTime.Today || x.SchedDate.Date == serverTime.Date)
                                        .SelectMany(x => x.Ops.Select(y => new Signalod()
            {
                IType       = InvalidType.Schedules,
                DateViewing = x.SchedDate,
                FKey        = y,
                FKeyType    = KeyType.Operatory,
            }))
                                        .ToArray();
            //Make a array of signals for every provider involved.
            Schedule[] arrayProviderSchedules = arraySchedules.Where(x => x.ProvNum > 0).ToArray();
            Signalod[] arrayProviderSignals   = arrayProviderSchedules
                                                .Where(x => x.SchedDate.Date == DateTime.Today || x.SchedDate.Date == serverTime.Date)
                                                .Select(x => new Signalod()
            {
                IType       = InvalidType.Schedules,
                DateViewing = x.SchedDate,
                FKey        = x.ProvNum,
                FKeyType    = KeyType.Provider,
            })
                                                .ToArray();
            Signalod[] arrayUniqueSignals = arrayOpSignals.Union(arrayProviderSignals).ToArray();
            if (arrayUniqueSignals.Length > 1000)
            {
                //We've had offices insert tens of thousands of signals at once which severely slowed down their database.
                Signalod signal = new Signalod {
                    IType       = InvalidType.Schedules,
                    DateViewing = DateTime.MinValue,                  //This will cause every workstation to refresh regardless of what they're viewing.
                };
                Insert(signal);
                return;
            }
            Insert(arrayUniqueSignals);
        }
Ejemplo n.º 23
0
        ///<summary>Process all Signals and Acks Since a given DateTime.  Only to be used by OpenDentalWebService.
        ///Returns latest valid signal Date/Time and the list of InvalidTypes that were refreshed.
        ///Can throw exception.</summary>
        public static List <InvalidType> RefreshForWeb()
        {
            InvalidTypeHistory.InitIfNecessary();
            int defaultProcessSigsIntervalInSecs = 7;

            ODException.SwallowAnyException(() => defaultProcessSigsIntervalInSecs = PrefC.GetInt(PrefName.ProcessSigsIntervalInSecs));
            if (DateTime.Now.Subtract(SignalLastRefreshedWeb) <= TimeSpan.FromSeconds(defaultProcessSigsIntervalInSecs))
            {
                return(new List <InvalidType>());
            }
            InvalidType[] arrayInvalidTypes = new InvalidType[0];
            //No need to check RemotingRole; no call to db.
            List <Signalod> listSignals = new List <Signalod>();

            try {
                if (SignalLastRefreshedWeb.Year < 1880)                //First signals for this session so go back in time a bit.
                {
                    SignalLastRefreshedWeb = MiscData.GetNowDateTime().AddSeconds(-1);
                }
                listSignals = Signalods.RefreshTimed(SignalLastRefreshedWeb);
                if (listSignals.Count > 0)                  //Next lower bound is current upper bound.
                {
                    SignalLastRefreshedWeb = listSignals.Max(x => x.SigDateTime);
                }
                arrayInvalidTypes = Signalods.GetInvalidTypesForWeb(listSignals);
                //Get all invalid types since given time and refresh the cache for those given invalid types.
                Cache.Refresh(arrayInvalidTypes);
            }
            catch (Exception e) {
                //Most likely cause for an exception here would be a thread collision between 2 consumers trying to refresh the cache at the exact same instant.
                //There is a chance that performing as subsequent refresh here would cause yet another collision but it's the best we can do without redesigning the entire cache pattern.
                Cache.Refresh(InvalidType.AllLocal);
                //Reset the last signal process time.
                DateTime dateTimeNow = DateTime.Now;
                ODException.SwallowAnyException(() => dateTimeNow = OpenDentBusiness.MiscData.GetNowDateTime());
                SignalLastRefreshedWeb = dateTimeNow;
                throw new Exception("Server cache may be invalid. Please try again. Error: " + e.Message);
            }
            InvalidTypeHistory.UpdateStatus(SignalLastRefreshedWeb, listSignals, arrayInvalidTypes);
            return(arrayInvalidTypes.ToList());
        }
Ejemplo n.º 24
0
        ///<summary>Will throw an exception if already clocked out.</summary>
        public static void ClockOut(long employeeNum, TimeClockStatus clockStatus)
        {
            ClockEvent clockEvent = ClockEvents.GetLastEvent(employeeNum);

            if (clockEvent == null)           //new employee never clocked in
            {
                throw new Exception(Lans.g("ClockEvents", "Error.  New employee never clocked in."));
            }
            else if (clockEvent.ClockStatus == TimeClockStatus.Break)           //only incomplete breaks will have been returned.
            {
                throw new Exception(Lans.g("ClockEvents", "Error.  Already clocked out for break."));;
            }
            else                                              //normal clock in/out
            {
                if (clockEvent.TimeDisplayed2.Year < 1880)    //clocked in.
                {
                    if (clockStatus == TimeClockStatus.Break) //clocking out on break
                    //leave the half-finished event alone and start a new one
                    {
                        clockEvent             = new ClockEvent();
                        clockEvent.EmployeeNum = employeeNum;
                        clockEvent.ClockStatus = TimeClockStatus.Break;
                        ClockEvents.Insert(clockEvent); //times handled
                    }
                    else                                //finish the existing event
                    {
                        clockEvent.TimeEntered2   = MiscData.GetNowDateTime();
                        clockEvent.TimeDisplayed2 = clockEvent.TimeEntered2;
                        clockEvent.ClockStatus    = clockStatus;                   //whatever the user selected
                        ClockEvents.Update(clockEvent);
                    }
                }
                else                  //clocked out for home or lunch.
                {
                    throw new Exception(Lans.g("ClockEvents", "Error.  Already clocked out."));
                }
            }
        }
Ejemplo n.º 25
0
        ///<summary>Archives first by moving to WikiPageHist if it already exists.  Then, in either case, it inserts the new page.
        ///Does not delete drafts.</summary>
        public static long InsertAndArchive(WikiPage wikiPage)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                wikiPage.WikiPageNum = Meth.GetLong(MethodBase.GetCurrentMethod(), wikiPage);
                return(wikiPage.WikiPageNum);
            }
            wikiPage.PageContentPlainText = MarkupEdit.ConvertToPlainText(wikiPage.PageContent);
            wikiPage.IsDraft = false;
            WikiPage wpExisting = GetByTitle(wikiPage.PageTitle);

            if (wpExisting != null)
            {
                WikiPageHist wpHist = PageToHist(wpExisting);
                WikiPageHists.Insert(wpHist);
                wikiPage.DateTimeSaved = MiscData.GetNowDateTime();
                //Old behavior was to delete the wiki page and then always insert.
                //It was changed to Update here for storing wiki page references by WikiPageNum instead of PageTitle
                //See JobNum 4429 for additional information.
                Crud.WikiPageCrud.Update(wikiPage);
                return(wikiPage.WikiPageNum);
            }
            //Deleted(archived) wp with the same page title should be updated with new page content. No need to create a new wp if the wikipage exist already.
            WikiPage wpDeleted = GetByTitle(wikiPage.PageTitle, isDeleted: true);

            if (wpDeleted != null)
            {
                //No need to add history since we already added the history when we archived it.
                wikiPage.WikiPageNum   = wpDeleted.WikiPageNum;
                wikiPage.DateTimeSaved = wpDeleted.DateTimeSaved;
                Crud.WikiPageCrud.Update(wikiPage);
                return(wikiPage.WikiPageNum);
            }
            //At this point the wp does not exist. Insert new a new wikipage.
            return(Crud.WikiPageCrud.Insert(wikiPage));
        }
Ejemplo n.º 26
0
        ///<summary>Process all Signals and Acks Since a given DateTime.  Only to be used by OpenDentalWebService.
        ///Returns latest valid signal Date/Time and the list of InvalidTypes that were refreshed.
        ///Can throw exception.</summary>
        public static List <InvalidType> RefreshForWeb()
        {
            int defaultProcessSigsIntervalInSecs = 7;

            ODException.SwallowAnyException(() => defaultProcessSigsIntervalInSecs = PrefC.GetInt(PrefName.ProcessSigsIntervalInSecs));
            if (DateTime.Now.Subtract(_signalLastRefreshedWeb) <= TimeSpan.FromSeconds(defaultProcessSigsIntervalInSecs))
            {
                return(new List <InvalidType>());
            }
            InvalidType[] arrayInvalidTypes = new InvalidType[0];
            //No need to check RemotingRole; no call to db.
            try {
                if (_signalLastRefreshedWeb.Year < 1880)
                {
                    _signalLastRefreshedWeb = MiscData.GetNowDateTime();
                }
                arrayInvalidTypes = Signalods.GetInvalidTypesForWeb(Signalods.RefreshTimed(_signalLastRefreshedWeb));
                //Get all invalid types since given time and refresh the cache for those given invalid types.
                Cache.Refresh(arrayInvalidTypes);
            }
            catch (Exception e) {
                //Most likely cause for an exception here would be a thread collision between 2 consumers trying to refresh the cache at the exact same instant.
                //There is a chance that performing as subsequent refresh here would cause yet another collision but it's the best we can do without redesigning the entire cache pattern.
                Cache.Refresh(InvalidType.AllLocal);
                throw new Exception("Server cache may be invalid. Please try again. Error: " + e.Message);
            }
            finally {
                DateTime dateTimeNow = DateTime.Now;
                try {
                    dateTimeNow = OpenDentBusiness.MiscData.GetNowDateTime();
                }
                catch (Exception) { }
                _signalLastRefreshedWeb = dateTimeNow;
            }
            return(arrayInvalidTypes.ToList());
        }
Ejemplo n.º 27
0
        ///<summary>This does all the validation before calling AlterLinkedEntries.  It had to be separated like this because of the complexity of saving a payment.  Surround with try-catch.  Will throw an exception if user is trying to change, but not allowed.  Will return false if no synch with accounting is needed.  Use -1 for newAcct to indicate no change.</summary>
        public static bool ValidateLinkedEntries(double oldAmt, double newAmt, bool isNew, long payNum, long newAcct)
        {
            //No need to check RemotingRole; no call to db.
            if (!Accounts.PaymentsLinked())
            {
                return(false);               //user has not even set up accounting links, so no need to check any of this.
            }
            bool amtChanged = false;

            if (oldAmt != newAmt)
            {
                amtChanged = true;
            }
            Transaction trans = Transactions.GetAttachedToPayment(payNum); //this gives us the oldAcctNum

            if (trans == null && (newAcct == 0 || newAcct == -1))          //if there was no previous link, and there is no attempt to create a link
            {
                return(false);                                             //no synch needed
            }
            if (trans == null)                                             //no previous link, but user is trying to create one. newAcct>0.
            {
                return(true);                                              //new transaction will be required
            }
            //at this point, we have established that there is a previous transaction.
            //If payment is attached to a transaction which is more than 48 hours old, then not allowed to change.
            if (amtChanged && trans.DateTimeEntry < MiscData.GetNowDateTime().AddDays(-2))
            {
                throw new ApplicationException(Lans.g("Payments", "Not allowed to change amount that is more than 48 hours old.  This payment is already attached to an accounting transaction.  You will need to detach it from within the accounting section of the program."));
            }
            if (amtChanged && Transactions.IsReconciled(trans))
            {
                throw new ApplicationException(Lans.g("Payments", "Not allowed to change amount.  This payment is attached to an accounting transaction that has been reconciled.  You will need to detach it from within the accounting section of the program."));
            }
            List <JournalEntry> jeL = JournalEntries.GetForTrans(trans.TransactionNum);
            long         oldAcct    = 0;
            JournalEntry jeDebit    = null;
            JournalEntry jeCredit   = null;
            double       absOld     = oldAmt;//the absolute value of the old amount

            if (oldAmt < 0)
            {
                absOld = -oldAmt;
            }
            for (int i = 0; i < jeL.Count; i++)       //we make sure down below that this count is exactly 2.
            {
                if (Accounts.GetAccount(jeL[i].AccountNum).AcctType == AccountType.Asset)
                {
                    oldAcct = jeL[i].AccountNum;
                }
                if (jeL[i].DebitAmt == absOld)
                {
                    jeDebit = jeL[i];
                }
                //old credit entry
                if (jeL[i].CreditAmt == absOld)
                {
                    jeCredit = jeL[i];
                }
            }
            if (jeCredit == null || jeDebit == null)
            {
                throw new ApplicationException(Lans.g("Payments", "Not able to automatically make changes in the accounting section to match the change made here.  You will need to detach it from within the accounting section."));
            }
            if (oldAcct == 0)          //something must have gone wrong.  But this should never happen
            {
                throw new ApplicationException(Lans.g("Payments", "Could not locate linked transaction.  You will need to detach it manually from within the accounting section of the program."));
            }
            if (newAcct == 0)          //detaching it from a linked transaction.
            //We will delete the transaction
            {
                return(true);
            }
            bool acctChanged = false;

            if (newAcct != -1 && oldAcct != newAcct)
            {
                acctChanged = true;              //changing linked acctNum
            }
            if (!amtChanged && !acctChanged)
            {
                return(false);               //no changes being made to amount or account, so no synch required.
            }
            if (jeL.Count != 2)
            {
                throw new ApplicationException(Lans.g("Payments", "Not able to automatically change the amount in the accounting section to match the change made here.  You will need to detach it from within the accounting section."));
            }
            //Amount or account changed on an existing linked transaction.
            return(true);
        }
Ejemplo n.º 28
0
 ///<summary>Poll the existing PayConnectResponseWeb for status changes.
 ///This method will update the ResponseJSON/ProcessingStatus with any changes</summary>
 public static void GetPaymentStatus(PayConnectResponseWeb responseWeb)
 {
     #region Response Object
     var resObj = new {
         Amount            = -1.00,
         TransactionType   = "",
         TransactionStatus = "",
         TransactionDate   = DateTime.MinValue,
         StatusDescription = "",
         //Used to poll for getting the payment status to see if the user has made a payment.
         PayToken             = "",
         CreditCardNumber     = "",
         CreditCardExpireDate = "",
         TransactionID        = -1,
         RefNumber            = "",
         Pending = true,
         Status  = new {
             code        = -1,
             description = "",
         },
         Messages = new {
             Message = new string[0]
         },
         //Used for future payments with this card.  Do not confuse this with PayToken.
         PaymentToken = new {
             TokenId    = "",
             Expiration = new {
                 month = "",
                 year  = "",
             },
             Messages = new {
                 Message = new string[0]
             },
         },
     };
     #endregion
     List <string> listHeaders = GetClientRequestHeadersForWebURL();
     listHeaders.Add("AccountToken: " + responseWeb.AccountToken);
     try {
         var res = Request(ApiRoute.PaymentStatus, HttpMethod.Get, listHeaders, "", resObj, $"?payToken={responseWeb.PayToken}");
         if (res == null)
         {
             PayConnectResponseWebs.HandleResponseError(responseWeb, JsonConvert.SerializeObject(res));
             throw new ODException("Invalid response from PayConnect.");
         }
         int    code    = -1;
         string codeMsg = "";
         if (res.Status != null)
         {
             code    = res.Status.code;
             codeMsg = "Response code: " + res.Status.code + "\r\n";
         }
         if (code > 0)
         {
             string err = "Invalid response from PayConnect.\r\nResponse code: " + code;
             if (res.Messages != null && res.Messages.Message != null && res.Messages.Message.Length > 0)
             {
                 err += "\r\nError retrieving payment status.\r\nResponse message(s):\r\n" + string.Join("\r\n", res.Messages.Message);
             }
             PayConnectResponseWebs.HandleResponseError(responseWeb, JsonConvert.SerializeObject(res));
             throw new ODException(err);
         }
         if (res.Pending)
         {
             HandleResponseSuccess(responseWeb, JsonConvert.SerializeObject(res), true);
         }
         else if (res.TransactionStatus != null &&
                  (res.TransactionStatus.Contains("Timeout") || res.TransactionStatus.Contains("Cancelled") || res.TransactionStatus.Contains("Declined")))
         {
             responseWeb.LastResponseStr  = JsonConvert.SerializeObject(res);
             responseWeb.ProcessingStatus = res.TransactionStatus.Contains("Declined") ? PayConnectWebStatus.Declined
                                         : (res.TransactionStatus.Contains("Cancelled") ? PayConnectWebStatus.Cancelled : PayConnectWebStatus.Expired);
             responseWeb.DateTimeExpired = MiscData.GetNowDateTime();
         }
         else if (res.TransactionStatus != null && res.TransactionStatus.Contains("Approved"))
         {
             string expYear  = res.PaymentToken.Expiration.year.Substring(res.PaymentToken.Expiration.year.Length - 2); //Last 2 digits only
             string expMonth = res.PaymentToken.Expiration.month.PadLeft(2, '0');                                       //2 digit month with leading 0 if needed
             responseWeb.PaymentToken = res.PaymentToken.TokenId;
             responseWeb.ExpDateToken = expYear + expMonth;                                                             //yyMM format
             responseWeb.RefNumber    = res.RefNumber;
             responseWeb.TransType    = PayConnectService.transType.SALE;
             HandleResponseSuccess(responseWeb, JsonConvert.SerializeObject(res), res.Pending);
         }
         else
         {
             responseWeb.LastResponseStr   = JsonConvert.SerializeObject(res);
             responseWeb.ProcessingStatus  = PayConnectWebStatus.Unknown;
             responseWeb.DateTimeLastError = MiscData.GetNowDateTime();
         }
     }
     catch (Exception ex) {
         PayConnectResponseWebs.HandleResponseError(responseWeb, ex.Message);
         throw;
     }
 }
Ejemplo n.º 29
0
            ///<summary>Returns number of pending transactions remaining after completion.</summary>
            private static int ProcessOutstandingTransactions()
            {
                OnLoggerEvent("Checking for outstanding PaymentTokens.");
                List <PayConnectResponseWeb> listPendingPaymentsAll = PayConnectResponseWebs.GetAllPending();
                //Only process if it's been >= 5 seconds.
                List <PayConnectResponseWeb> listPendingDue = listPendingPaymentsAll.FindAll(x => DateTime.Now.Subtract(x.GetLastPendingUpdateDateTime()) > TimeSpan.FromSeconds(5));

                OnLoggerEvent("Found " + listPendingPaymentsAll.Count + " PaymentTokens. " + listPendingDue.Count.ToString() + " are due to be processed.");
                if (listPendingDue.Count <= 0)                //None are due this time around but we may have some still pending, return count of those.
                {
                    return(listPendingPaymentsAll.Count);
                }
                OnLoggerEvent("Processing " + listPendingDue.Count.ToString() + " outstanding PaymentTokens.", LogLevel.Information);
                //Seed total remaining with any that we won't be processing this time around.
                int remaining = listPendingPaymentsAll.Count - listPendingDue.Count;

                foreach (PayConnectResponseWeb responseWebCur in listPendingDue)
                {
                    try {
                        //This method will update the responseWebCur with all of the data from the /paymentStatus API call
                        PayConnectREST.GetPaymentStatus(responseWebCur);
                        switch (responseWebCur.ProcessingStatus)
                        {
                        case PayConnectWebStatus.Pending:
                            //No new status to report. Try again next time.
                            OnLoggerEvent("PaymentToken still pending: " + responseWebCur.PayToken, LogLevel.Information);
                            if (DateTime.Now.AddMinutes(30) < responseWebCur.GetLastPendingUpdateDateTime())
                            {
                                //Expire this transaction ourselves after 30 minutes.  In testing, PayConnect expires them after 15 minutes.
                                responseWebCur.ProcessingStatus = PayConnectWebStatus.Expired;
                                responseWebCur.DateTimeExpired  = MiscData.GetNowDateTime();
                                OnLoggerEvent("PaymentToken has expired: " + responseWebCur.PayToken, LogLevel.Information);
                            }
                            break;

                        case PayConnectWebStatus.CreatedError:
                        case PayConnectWebStatus.PendingError:
                            OnLoggerEvent("PaymentToken returned an error when retreiving a status update: " + responseWebCur.PayToken, LogLevel.Information);
                            break;

                        case PayConnectWebStatus.Expired:
                            OnLoggerEvent("PaymentToken has expired: " + responseWebCur.PayToken, LogLevel.Information);
                            break;

                        case PayConnectWebStatus.Completed:
                            OnLoggerEvent("PaymentToken has been completed: " + responseWebCur.PayToken, LogLevel.Information);
                            if (responseWebCur.IsTokenSaved)
                            {
                                CreditCards.InsertFromPayConnect(responseWebCur);
                            }
                            Patient pat       = Patients.GetPat(responseWebCur.PatNum);
                            long    clinicNum = 0;
                            if (PrefC.HasClinicsEnabled)
                            {
                                clinicNum = pat.ClinicNum;
                            }
                            string receipt = "";
                            if (!string.IsNullOrWhiteSpace(responseWebCur.LastResponseStr))
                            {
                                var pcInfo = Newtonsoft.Json.JsonConvert.DeserializeAnonymousType(responseWebCur.LastResponseStr,
                                                                                                  new { Amount = (decimal)0.0, CreditCardNumber = "", Messages = new { Message = new string[0] }, RefNumber = "", Status = new { description = "" }, }
                                                                                                  );
                                receipt = BuildReceiptString(PayConnectService.transType.SALE, pcInfo.RefNumber, "", pcInfo.CreditCardNumber, "", "", pcInfo.Status?.description ?? "", pcInfo.Messages.Message.ToList(), pcInfo.Amount, 0, clinicNum);
                            }
                            responseWebCur.PayNum = Payments.InsertFromPayConnect(pat.PatNum, pat.PriProv, clinicNum, responseWebCur.Amount, responseWebCur.GetFormattedNote(true), receipt, responseWebCur.CCSource);
                            break;

                        case PayConnectWebStatus.Cancelled:
                            OnLoggerEvent("PaymentToken has been cancelled: " + responseWebCur.PayToken, LogLevel.Information);
                            break;

                        case PayConnectWebStatus.Declined:
                            OnLoggerEvent("PaymentToken has been declined: " + responseWebCur.PayToken, LogLevel.Information);
                            break;

                        case PayConnectWebStatus.Created:
                        case PayConnectWebStatus.Unknown:
                        case PayConnectWebStatus.UnknownError:
                        default:
                            OnLoggerEvent($"PaymentToken {responseWebCur.PayToken} returned unsupported state: {responseWebCur.ProcessingStatus.ToString()}", LogLevel.Information);
                            break;
                        }
                    }
                    catch (Exception e) {
                        e.DoNothing();
                    }
                    finally {
                        PayConnectResponseWebs.Update(responseWebCur);
                    }
                }
                remaining = listPendingPaymentsAll.FindAll(x => x.ProcessingStatus == PayConnectWebStatus.Pending).Count;
                OnLoggerEvent(remaining.ToString() + " PaymentTokens still pending after processing.", LogLevel.Information);
                return(remaining);
            }
Ejemplo n.º 30
0
 ///<summary>Make a payment using HPF directly.  Throws exceptions.</summary>
 public static void MakePaymentWithAlias(Patient pat, string payNote, double amount, CreditCard cc)
 {
     if (pat == null)
     {
         throw new ODException("No Patient Found", ODException.ErrorCodes.NoPatientFound);
     }
     if (amount < 0.00 || amount > 99999.99)
     {
         throw new ODException("Invalid Amount", ODException.ErrorCodes.OtkArgsInvalid);
     }
     if (string.IsNullOrEmpty(payNote))
     {
         throw new ODException("Invalid PayNote", ODException.ErrorCodes.OtkArgsInvalid);
     }
     if (cc == null)
     {
         throw new ODException("No Credit Card Found", ODException.ErrorCodes.OtkArgsInvalid);
     }
     if (string.IsNullOrEmpty(cc.PayConnectToken))
     {
         throw new ODException("Invalid CC Alias", ODException.ErrorCodes.OtkArgsInvalid);
     }
     //request a PayConnect token, if a token was already saved PayConnect will return the same token,
     //otherwise replace CCNumberMasked with the returned token if the sale successful
     PayConnectService.creditCardRequest payConnectRequest = PayConnect.BuildSaleRequest(
         (decimal)amount, cc.PayConnectToken, cc.CCExpiration.Year, cc.CCExpiration.Month,
         pat.GetNameFLnoPref(), "", cc.Zip, null,
         PayConnectService.transType.SALE, "", true);
     //clinicNumCur could be 0, and the practice level or 'Headquarters' PayConnect credentials would be used for this charge
     PayConnectService.transResponse payConnectResponse = PayConnect.ProcessCreditCard(payConnectRequest, pat.ClinicNum,
                                                                                       x => throw new ODException(x));
     if (payConnectRequest != null && payConnectResponse.Status.code == 0)         //Success
     {
         string receipt = BuildReceiptString(payConnectRequest.TransType, payConnectResponse.RefNumber, payConnectRequest.NameOnCard, payConnectRequest.CardNumber,
                                             payConnectRequest.MagData, payConnectResponse.AuthCode, payConnectResponse.Status.description, payConnectResponse.Messages.ToList(), payConnectRequest.Amount,
                                             0, pat.ClinicNum);
         DateTime dateTimeProcessed = DateTime.Now;
         string   formattedNote     = Lans.g("PayConnect", "Amount:") + " " + amount.ToString("f") + "\r\n"
                                      + Lans.g("PayConnect", "Card Number:") + " " + cc.CCNumberMasked + "\r\n"
                                      + Lans.g("PayConnect", "Transaction ID:") + " " + payConnectRequest.RefNumber + "\r\n"
                                      + Lans.g("PayConnect", "Processed:") + " " + dateTimeProcessed.ToShortDateString() + " " + dateTimeProcessed.ToShortTimeString() + "\r\n"
                                      + Lans.g("PayConnect", "Note:") + " " + payNote;
         long payNum = Payments.InsertFromPayConnect(pat.PatNum, pat.PriProv, pat.ClinicNum, amount, formattedNote, receipt, CreditCardSource.PayConnectPortal);
         PayConnectResponseWeb responseWeb = new PayConnectResponseWeb()
         {
             Amount            = amount,
             PatNum            = pat.PatNum,
             ProcessingStatus  = PayConnectWebStatus.Completed,
             PayNote           = payNote,
             CCSource          = cc.CCSource,
             IsTokenSaved      = true,
             PayNum            = payNum,
             DateTimeCompleted = MiscData.GetNowDateTime(),
             RefNumber         = payConnectResponse.RefNumber,
             TransType         = PayConnectService.transType.SALE,
             PaymentToken      = cc.PayConnectToken,
         };
         //Insert a new payconnectresponse row for historical record in the transaction window.
         PayConnectResponseWebs.Insert(responseWeb);
     }
     else              //Failed
     {
         throw new ODException("Unable to process payment for this credit card: " + (payConnectResponse == null ? "Unknown error" : payConnectResponse.Status.description));
     }
 }