Ejemplo n.º 1
0
        ///<summary>Etrans type will be figured out by this class.  Either TextReport, Acknowledge_997, Acknowledge_999, or StatusNotify_277.</summary>
        public static void ProcessIncomingReport(DateTime dateTimeTrans, long clearinghouseNum, string messageText)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                Meth.GetVoid(MethodBase.GetCurrentMethod(), dateTimeTrans, clearinghouseNum, messageText);
                return;
            }
            Etrans etrans = new Etrans();

            etrans.DateTimeTrans    = dateTimeTrans;
            etrans.ClearingHouseNum = clearinghouseNum;
            EtransMessageText etransMessageText = new EtransMessageText();

            etransMessageText.MessageText = messageText;
            EtransMessageTexts.Insert(etransMessageText);
            etrans.EtransMessageTextNum = etransMessageText.EtransMessageTextNum;
            string command;

            if (X12object.IsX12(messageText))
            {
                X12object Xobj = new X12object(messageText);
                if (Xobj.IsAckInterchange())
                {
                    etrans.Etype = EtransType.Ack_Interchange;
                    Etranss.Insert(etrans);
                    //At some point in the future, we should use TA101 to match to batch number and TA104 to get the ack code,
                    //then update historic etrans entries like we do for 997s, 999s and 277s.
                }
                else if (Xobj.Is997())
                {
                    X997 x997 = new X997(messageText);
                    etrans.Etype       = EtransType.Acknowledge_997;
                    etrans.BatchNumber = x997.GetBatchNumber();
                    Etranss.Insert(etrans);
                    string batchack = x997.GetBatchAckCode();
                    if (batchack == "A" || batchack == "R")               //accepted or rejected
                    {
                        command = "UPDATE etrans SET AckCode='" + batchack + "', "
                                  + "AckEtransNum=" + POut.Long(etrans.EtransNum)
                                  + " WHERE BatchNumber=" + POut.Long(etrans.BatchNumber)
                                  + " AND ClearinghouseNum=" + POut.Long(clearinghouseNum)
                                  + " AND DateTimeTrans > " + POut.DateT(dateTimeTrans.AddDays(-14))
                                  + " AND DateTimeTrans < " + POut.DateT(dateTimeTrans.AddDays(1))
                                  + " AND AckEtransNum=0";
                        Db.NonQ(command);
                    }
                    else                      //partially accepted
                    {
                        List <int> transNums = x997.GetTransNums();
                        string     ack;
                        for (int i = 0; i < transNums.Count; i++)
                        {
                            ack = x997.GetAckForTrans(transNums[i]);
                            if (ack == "A" || ack == "R")                       //accepted or rejected
                            {
                                command = "UPDATE etrans SET AckCode='" + ack + "', "
                                          + "AckEtransNum=" + POut.Long(etrans.EtransNum)
                                          + " WHERE BatchNumber=" + POut.Long(etrans.BatchNumber)
                                          + " AND TransSetNum=" + POut.Long(transNums[i])
                                          + " AND ClearinghouseNum=" + POut.Long(clearinghouseNum)
                                          + " AND DateTimeTrans > " + POut.DateT(dateTimeTrans.AddDays(-14))
                                          + " AND DateTimeTrans < " + POut.DateT(dateTimeTrans.AddDays(1))
                                          + " AND AckEtransNum=0";
                                Db.NonQ(command);
                            }
                        }
                    }
                    //none of the other fields make sense, because this ack could refer to many claims.
                }
                else if (Xobj.Is999())
                {
                    X999 x999 = new X999(messageText);
                    etrans.Etype       = EtransType.Acknowledge_999;
                    etrans.BatchNumber = x999.GetBatchNumber();
                    Etranss.Insert(etrans);
                    string batchack = x999.GetBatchAckCode();
                    if (batchack == "A" || batchack == "R")               //accepted or rejected
                    {
                        command = "UPDATE etrans SET AckCode='" + batchack + "', "
                                  + "AckEtransNum=" + POut.Long(etrans.EtransNum)
                                  + " WHERE BatchNumber=" + POut.Long(etrans.BatchNumber)
                                  + " AND ClearinghouseNum=" + POut.Long(clearinghouseNum)
                                  + " AND DateTimeTrans > " + POut.DateT(dateTimeTrans.AddDays(-14))
                                  + " AND DateTimeTrans < " + POut.DateT(dateTimeTrans.AddDays(1))
                                  + " AND AckEtransNum=0";
                        Db.NonQ(command);
                    }
                    else                      //partially accepted
                    {
                        List <int> transNums = x999.GetTransNums();
                        string     ack;
                        for (int i = 0; i < transNums.Count; i++)
                        {
                            ack = x999.GetAckForTrans(transNums[i]);
                            if (ack == "A" || ack == "R")           //accepted or rejected
                            {
                                command = "UPDATE etrans SET AckCode='" + ack + "', "
                                          + "AckEtransNum=" + POut.Long(etrans.EtransNum)
                                          + " WHERE BatchNumber=" + POut.Long(etrans.BatchNumber)
                                          + " AND TransSetNum=" + POut.Long(transNums[i])
                                          + " AND ClearinghouseNum=" + POut.Long(clearinghouseNum)
                                          + " AND DateTimeTrans > " + POut.DateT(dateTimeTrans.AddDays(-14))
                                          + " AND DateTimeTrans < " + POut.DateT(dateTimeTrans.AddDays(1))
                                          + " AND AckEtransNum=0";
                                Db.NonQ(command);
                            }
                        }
                    }
                    //none of the other fields make sense, because this ack could refer to many claims.
                }
                else if (X277.Is277(Xobj))
                {
                    X277 x277 = new X277(messageText);
                    etrans.Etype = EtransType.StatusNotify_277;
                    Etranss.Insert(etrans);
                    List <string> claimTrackingNumbers = x277.GetClaimTrackingNumbers();
                    for (int i = 0; i < claimTrackingNumbers.Count; i++)
                    {
                        string ack      = x277.GetClaimInfo(claimTrackingNumbers[i])[3];
                        long   claimNum = Claims.GetClaimNumForIdentifier(claimTrackingNumbers[i]);
                        //Locate the latest etrans entries for the claim based on DateTimeTrans with EType of ClaimSent or Claim_Ren and update the AckCode and AckEtransNum.
                        //We overwrite existing acks from 997s, 999s and older 277s.
                        command = "UPDATE etrans SET AckCode='" + ack + "', "
                                  + "AckEtransNum=" + POut.Long(etrans.EtransNum)
                                  + " WHERE EType IN (0,3) "                     //ClaimSent and Claim_Ren
                                  + " AND ClaimNum=" + POut.Long(claimNum)
                                  + " AND ClearinghouseNum=" + POut.Long(clearinghouseNum)
                                  + " AND DateTimeTrans > " + POut.DateT(dateTimeTrans.AddDays(-14))
                                  + " AND DateTimeTrans < " + POut.DateT(dateTimeTrans.AddDays(1));
                        Db.NonQ(command);
                    }
                    ////none of the other fields make sense, because this ack could refer to many claims.
                }
                else                  //unknown type of X12 report.
                {
                    etrans.Etype = EtransType.TextReport;
                    Etranss.Insert(etrans);
                }
            }
            else              //not X12
            {
                etrans.Etype = EtransType.TextReport;
                Etranss.Insert(etrans);
            }
        }
Ejemplo n.º 2
0
        ///<summary>Returns a blank string if there were no errors while attempting to update internal carriers using iTrans n-cpl.json file.</summary>
        public static string TryCarrierUpdate(bool isAutomatic = true, ItransImportFields fieldsToImport = ItransImportFields.None)
        {
            string        json;
            DateTime      dateTimeTrans = DateTime.Now;
            Clearinghouse clearinghouse = Clearinghouses.GetDefaultDental();

            if (clearinghouse == null)
            {
                return(Lans.g("Clearinghosue", "Unable to update. No default dental clearinghouse set."));
            }
            //If ITRANS2 is fully setup, then use the local ITRANS2 install on server to import carrier data.
            if (clearinghouse.CommBridge == EclaimsCommBridge.ITRANS && !string.IsNullOrEmpty(clearinghouse.ResponsePath))
            {
                if (!File.Exists(ODFileUtils.CombinePaths(clearinghouse.ResponsePath, "ITRANS Claims Director.exe")))
                {
                    return(Lans.g("Clearinghouse", "Unable to find 'ITRANS Claims Director.exe'. Make sure the file exists and the path is correct."));
                }
                if (isAutomatic && PrefC.GetString(PrefName.WebServiceServerName).ToLower() != Dns.GetHostName().ToLower())               //Only server can run when isOnlyServer is true.
                {
                    return(Lans.g("Clearinghouse", "Update can only run on the web service server " + PrefC.GetString(PrefName.WebServiceServerName)) +
                           ". " + Lans.g("Clearinghouse", "Connect to the server and try again."));
                }
                Process process = new Process {
                    StartInfo = new ProcessStartInfo {
                        FileName  = ODFileUtils.CombinePaths(clearinghouse.ResponsePath, "ITRANS Claims Director.exe"),
                        Arguments = " --getncpl"
                    }
                };
                process.Start();
                process.WaitForExit();
                string ncplFilePath = ODFileUtils.CombinePaths(clearinghouse.ResponsePath, "n-cpl.json");
                json          = File.ReadAllText(ncplFilePath);     //Read n-cpl.json
                dateTimeTrans = File.GetCreationTime(ncplFilePath);
            }
            else              //ITRANS2 not used or not setup correctly, go to HQ for file content.
            {
                try {
                    string result = WebServiceMainHQProxy.GetWebServiceMainHQInstance().CanadaCarrierUpdate(PayloadHelper.CreatePayload("", eServiceCode.Undefined));
                    json = WebSerializer.DeserializePrimitiveOrThrow <string>(result);
                }
                catch (Exception ex) {
                    return(Lans.g("Clearinghouse", "Unable to update carrier list from HQ web services.") + "\r\n" + ex.Message.ToString());
                }
            }
            EtransMessageText msgTextPrev = EtransMessageTexts.GetMostRecentForType(EtransType.ItransNcpl);

            if (msgTextPrev != null && msgTextPrev.MessageText == json)
            {
                if (isAutomatic ||
                    ODMessageBox.Show("Carrier list has not changed since last checked.\r\nContinue?", "", MessageBoxButtons.YesNo) != DialogResult.Yes)
                {
                    return(Lans.g("Clearinghouse", "Carrier list has not changed since last checked."));                  //json has not changed since we last checked, no need to update.
                }
            }
            //Save json as new etrans entry.
            Etrans etrans = Etranss.CreateEtrans(dateTimeTrans, clearinghouse.HqClearinghouseNum, json, 0);

            etrans.Etype = EtransType.ItransNcpl;
            Etranss.Insert(etrans);
            ItransNCpl iTransNCpl = null;

            try {
                iTransNCpl = JsonConvert.DeserializeObject <ItransNCpl>(json);             //Deserialize n-cpl.json
            }
            catch (Exception ex) {
                ex.DoNothing();
                return(Lans.g("Clearinghouse", "Failed to import json."));
            }
            List <CanadianNetwork> listCanadianNetworks = CanadianNetworks.GetDeepCopy();
            //List of carriers from json file that were matched by electId to multiple internal carriers
            List <Carrier> listUnmatchedJsonCarriers = new List <Carrier>();
            List <long>    listMatchedDbCarrierNums  = new List <long> ();

            foreach (ItransNCpl.Carrier jsonCarrier in iTransNCpl.ListCarriers) //Update carriers.
            {
                string jsonCarrierPhone = jsonCarrier.Telephone?.First().Value; //Will be empty string if not found.
                List <OpenDentBusiness.Carrier> listDbCarriers = Carriers.GetAllByElectId(jsonCarrier.Bin).FindAll(x => x.IsCDA);
                if (listDbCarriers.Count > 1)                                   //Some Canadian carriers share ElectId, need to filter further.  This happens with carrier resellers.
                {
                    #region Additional matching based on phone numbers, 'continues' loop if a single match is not found.
                    List <OpenDentBusiness.Carrier> listPhoneMatchedDbCarriers = listDbCarriers.FindAll(x =>
                                                                                                        TelephoneNumbers.AreNumbersEqual(x.Phone, jsonCarrierPhone)
                                                                                                        );
                    if (listPhoneMatchedDbCarriers.Count != 1)                   //Either 0 or multiple matches, either way do not update any carriers.
                    //When 0 matches found:	jsonCarrier changed their phone number, can not determine which carrier to update.
                    //E.G. - JsonCarrier A matched to OD carriers B and C by electId.
                    //Phone number from JsonCarrier A did not match either carrier B or C due to jsonCarrier phone number change.
                    //Future iterations for jsonCarrier D might match to carrier B or C if phone number for jsonCarrier D did not change.
                    //If jsonCarrier D is matched to single OD carrier, then jsonCarrier A will attempt to match near end of method to a unmatched internal carrier.
                    //If ther are no future matches to OD carrier B or C then all unmatched jsonCarriers will not be imported and no OD carries will not be updated.
                    //----------------------------------------------------------------------//
                    //When greater than 1:	jsonCarrier number not changed and both internal carriers have matching electIds and phone numbers.
                    //This should be rare, most likely a setup error.
                    //There should not be multiple carriers that share electId and phone numbers. User should change or remove one of the matched carriers.
                    {
                        listUnmatchedJsonCarriers.Add(jsonCarrier);
                        continue;
                    }
                    listDbCarriers = listPhoneMatchedDbCarriers;
                    #endregion
                }
                //At this point listDbCarriers should either be empty or contain a single OD carrier.
                OpenDentBusiness.Carrier carrierInDb = listDbCarriers.FirstOrDefault(); //Null if list is empty.
                if (carrierInDb == null)                                                //Carrier can not be matched to internal Carrier based on ElectID.
                {
                    #region Insert new carrier
                    if (!fieldsToImport.HasFlag(ItransImportFields.AddMissing))
                    {
                        continue;
                    }
                    OpenDentBusiness.Carrier carrierNew = new OpenDentBusiness.Carrier();
                    carrierNew.CanadianEncryptionMethod = 1;                  //Default.  Deprecated for all Canadian carriers and will never be any other value.
                    TrySetCanadianNetworkNum(jsonCarrier, carrierNew, listCanadianNetworks);
                    carrierNew.ElectID     = jsonCarrier.Bin;
                    carrierNew.IsCDA       = true;
                    carrierNew.CarrierName = jsonCarrier.Name.En;
                    carrierNew.Phone       = TelephoneNumbers.AutoFormat(jsonCarrierPhone);
                    if (jsonCarrier.Address.Count() > 0)
                    {
                        Address add = jsonCarrier.Address.First();
                        carrierNew.Address  = add.Street1;
                        carrierNew.Address2 = add.Street2;
                        carrierNew.City     = add.City;
                        carrierNew.State    = add.Province;
                        carrierNew.Zip      = add.Postal_Code;
                    }
                    carrierNew.CanadianSupportedTypes = GetSupportedTypes(jsonCarrier);
                    carrierNew.CDAnetVersion          = POut.Int(jsonCarrier.Versions.Max(x => PIn.Int(x))).PadLeft(2, '0');        //Version must be in 2 digit format. ex. 02.
                    carrierNew.CarrierName            = jsonCarrier.Name.En;
                    try {
                        Carriers.Insert(carrierNew);
                    }
                    catch (Exception ex) {
                        ex.DoNothing();
                    }
                    #endregion
                    continue;
                }
                listMatchedDbCarrierNums.Add(carrierInDb.CarrierNum);
                UpdateCarrierInDb(carrierInDb, jsonCarrier, listCanadianNetworks, fieldsToImport, jsonCarrierPhone, isAutomatic);
            }
            foreach (Carrier jsonCarrier in listUnmatchedJsonCarriers)
            {
                List <OpenDentBusiness.Carrier> listDbCarriers = Carriers.GetWhere(x => x.IsCDA &&
                                                                                   x.ElectID == jsonCarrier.Bin && !listMatchedDbCarrierNums.Contains(x.CarrierNum)
                                                                                   );
                if (listDbCarriers.Count != 1)               //Either 0 or multiple matches, either way do not update any carriers.
                {
                    continue;
                }
                OpenDentBusiness.Carrier carrierInDb = listDbCarriers.FirstOrDefault();
                string jsonCarrierPhone = jsonCarrier.Telephone?.First().Value;
                UpdateCarrierInDb(carrierInDb, jsonCarrier, listCanadianNetworks, fieldsToImport, jsonCarrierPhone, isAutomatic);
            }
            return("");           //Blank string represents a completed update.
        }
Ejemplo n.º 3
0
        ///<summary>Sets the status of the claim to sent, usually as part of printing.  Also makes an entry in etrans.  If this is Canadian eclaims, then this function gets run first.  If the claim is to be sent elecronically, then the messagetext is created after this method and an attempt is made to send the claim.  Finally, the messagetext is added to the etrans.  This is necessary because the transaction numbers must be incremented and assigned to each claim before creating the message and attempting to send.  For Canadians, it will always record the attempt as an etrans even if claim is not set to status of sent.</summary>
        public static Etrans SetClaimSentOrPrinted(long claimNum, long patNum, long clearinghouseNum, EtransType etype, int batchNumber)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                return(Meth.GetObject <Etrans>(MethodBase.GetCurrentMethod(), claimNum, patNum, clearinghouseNum, etype, batchNumber));
            }
            string command;
            Etrans etrans = new Etrans();

            //etrans.DateTimeTrans handled automatically
            etrans.ClearingHouseNum = clearinghouseNum;
            etrans.Etype            = etype;
            etrans.ClaimNum         = claimNum;
            etrans.PatNum           = patNum;
            //Get the primary and secondary carrierNums for this claim.
            command = "SELECT carrier1.CarrierNum,carrier2.CarrierNum AS CarrierNum2 FROM claim "
                      + "LEFT JOIN insplan insplan1 ON insplan1.PlanNum=claim.PlanNum "
                      + "LEFT JOIN carrier carrier1 ON carrier1.CarrierNum=insplan1.CarrierNum "
                      + "LEFT JOIN insplan insplan2 ON insplan2.PlanNum=claim.PlanNum2 "
                      + "LEFT JOIN carrier carrier2 ON carrier2.CarrierNum=insplan2.CarrierNum "
                      + "WHERE claim.ClaimNum=" + POut.Long(claimNum);
            DataTable table = Db.GetTable(command);

            etrans.CarrierNum  = PIn.Long(table.Rows[0][0].ToString());
            etrans.CarrierNum2 = PIn.Long(table.Rows[0][1].ToString());          //might be 0 if no secondary on this claim
            etrans.BatchNumber = batchNumber;
            //if(X837.IsX12(messageText)) {
            //	X837 x837=new X837(messageText);
            //	etrans.TransSetNum=x837.GetTransNum(claimNum);
            //}
            if (etype == EtransType.Claim_CA || etype == EtransType.ClaimCOB_CA || etype == EtransType.Predeterm_CA || etype == EtransType.PredetermEOB_CA)
            {
                etrans.OfficeSequenceNumber = 0;
                //find the next officeSequenceNumber
                command = "SELECT MAX(OfficeSequenceNumber) FROM etrans";
                table   = Db.GetTable(command);
                if (table.Rows.Count > 0)
                {
                    etrans.OfficeSequenceNumber = PIn.Int(table.Rows[0][0].ToString());
                    if (etrans.OfficeSequenceNumber == 999999)                   //if the office has sent > 1 million messages, and has looped back around to 1.
                    {
                        throw new ApplicationException
                                  ("OfficeSequenceNumber has maxed out at 999999.  This program will need to be enhanced.");
                    }
                }
#if DEBUG
                etrans.OfficeSequenceNumber = PIn.Int(File.ReadAllText(@"..\..\..\TestCanada\LastOfficeSequenceNumber.txt"));
                File.WriteAllText(@"..\..\..\TestCanada\LastOfficeSequenceNumber.txt", (etrans.OfficeSequenceNumber + 1).ToString());
#endif
                etrans.OfficeSequenceNumber++;
                //find the next CarrierTransCounter for the primary carrier
                etrans.CarrierTransCounter = 0;
                command = "SELECT MAX(CarrierTransCounter) FROM etrans "
                          + "WHERE CarrierNum=" + POut.Long(etrans.CarrierNum);
                table = Db.GetTable(command);
                int tempcounter = 0;
                if (table.Rows.Count > 0)
                {
                    tempcounter = PIn.Int(table.Rows[0][0].ToString());
                }
                if (tempcounter > etrans.CarrierTransCounter)
                {
                    etrans.CarrierTransCounter = tempcounter;
                }
                command = "SELECT MAX(CarrierTransCounter2) FROM etrans "
                          + "WHERE CarrierNum2=" + POut.Long(etrans.CarrierNum);
                table = Db.GetTable(command);
                if (table.Rows.Count > 0)
                {
                    tempcounter = PIn.Int(table.Rows[0][0].ToString());
                }
                if (tempcounter > etrans.CarrierTransCounter)
                {
                    etrans.CarrierTransCounter = tempcounter;
                }
                if (etrans.CarrierTransCounter == 99999)
                {
                    throw new ApplicationException("CarrierTransCounter has maxed out at 99999.  This program will need to be enhanced.");
                }
                etrans.CarrierTransCounter++;
                if (etrans.CarrierNum2 > 0)               //if there is secondary coverage on this claim
                {
                    etrans.CarrierTransCounter2 = 1;
                    command = "SELECT MAX(CarrierTransCounter) FROM etrans "
                              + "WHERE CarrierNum=" + POut.Long(etrans.CarrierNum2);
                    table = Db.GetTable(command);
                    if (table.Rows.Count > 0)
                    {
                        tempcounter = PIn.Int(table.Rows[0][0].ToString());
                    }
                    if (tempcounter > etrans.CarrierTransCounter2)
                    {
                        etrans.CarrierTransCounter2 = tempcounter;
                    }
                    command = "SELECT MAX(CarrierTransCounter2) FROM etrans "
                              + "WHERE CarrierNum2=" + POut.Long(etrans.CarrierNum2);
                    table = Db.GetTable(command);
                    if (table.Rows.Count > 0)
                    {
                        tempcounter = PIn.Int(table.Rows[0][0].ToString());
                    }
                    if (tempcounter > etrans.CarrierTransCounter2)
                    {
                        etrans.CarrierTransCounter2 = tempcounter;
                    }
                    if (etrans.CarrierTransCounter2 == 99999)
                    {
                        throw new ApplicationException("CarrierTransCounter has maxed out at 99999.  This program will need to be enhanced.");
                    }
                    etrans.CarrierTransCounter2++;
                }
            }
            command = "UPDATE claim SET ClaimStatus = 'S',"
                      + "DateSent= " + POut.Date(MiscData.GetNowDateTime())
                      + " WHERE claimnum = " + POut.Long(claimNum);
            Db.NonQ(command);
            EtransMessageText etransMessageText = new EtransMessageText();
            etransMessageText.MessageText = "";
            EtransMessageTexts.Insert(etransMessageText);
            etrans.EtransMessageTextNum = etransMessageText.EtransMessageTextNum;
            Etranss.Insert(etrans);
            return(GetEtrans(etrans.EtransNum));           //Since the DateTimeTrans is set upon insert, we need to read the record again in order to get the date.
        }
Ejemplo n.º 4
0
		///<summary>Etrans type will be figured out by this class.  Either TextReport, Acknowledge_997, Acknowledge_999, or StatusNotify_277.</summary>
		public static void ProcessIncomingReport(DateTime dateTimeTrans,long hqClearinghouseNum,string messageText,long userNum) {
			if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
				Meth.GetVoid(MethodBase.GetCurrentMethod(),dateTimeTrans,hqClearinghouseNum,messageText,userNum);
				return;
			}
			Etrans etrans=CreateEtrans(dateTimeTrans,hqClearinghouseNum,messageText,userNum);
			string command;
			X12object Xobj=X12object.ToX12object(messageText);
			if(Xobj!=null) {//Is a correctly formatted X12 message.
				if(Xobj.IsAckInterchange()) {
					etrans.Etype=EtransType.Ack_Interchange;
					Etranss.Insert(etrans);
					//At some point in the future, we should use TA101 to match to batch number and TA104 to get the ack code, 
					//then update historic etrans entries like we do for 997s, 999s and 277s.
				}
				else if(Xobj.Is997()) {
					X997 x997=new X997(messageText);
					etrans.Etype=EtransType.Acknowledge_997;
					etrans.BatchNumber=x997.GetBatchNumber();
					Etranss.Insert(etrans);
					string batchack=x997.GetBatchAckCode();
					if(batchack=="A"||batchack=="R") {//accepted or rejected
						command="UPDATE etrans SET AckCode='"+batchack+"', "
							+"AckEtransNum="+POut.Long(etrans.EtransNum)
							+" WHERE BatchNumber="+POut.Long(etrans.BatchNumber)
							+" AND ClearinghouseNum="+POut.Long(hqClearinghouseNum)
							+" AND DateTimeTrans > "+POut.DateT(dateTimeTrans.AddDays(-14))
							+" AND DateTimeTrans < "+POut.DateT(dateTimeTrans.AddDays(1))
							+" AND AckEtransNum=0";
						Db.NonQ(command);
					}
					else {//partially accepted
						List<int> transNums=x997.GetTransNums();
						string ack;
						for(int i=0;i<transNums.Count;i++) {
							ack=x997.GetAckForTrans(transNums[i]);
							if(ack=="A"||ack=="R") {//accepted or rejected
								command="UPDATE etrans SET AckCode='"+ack+"', "
									+"AckEtransNum="+POut.Long(etrans.EtransNum)
									+" WHERE BatchNumber="+POut.Long(etrans.BatchNumber)
									+" AND TransSetNum="+POut.Long(transNums[i])
									+" AND ClearinghouseNum="+POut.Long(hqClearinghouseNum)
									+" AND DateTimeTrans > "+POut.DateT(dateTimeTrans.AddDays(-14))
									+" AND DateTimeTrans < "+POut.DateT(dateTimeTrans.AddDays(1))
									+" AND AckEtransNum=0";
								Db.NonQ(command);
							}
						}
					}
					//none of the other fields make sense, because this ack could refer to many claims.
				}
				else if(Xobj.Is999()) {
					X999 x999=new X999(messageText);
					etrans.Etype=EtransType.Acknowledge_999;
					etrans.BatchNumber=x999.GetBatchNumber();
					Etranss.Insert(etrans);
					string batchack=x999.GetBatchAckCode();
					if(batchack=="A"||batchack=="R") {//accepted or rejected
					  command="UPDATE etrans SET AckCode='"+batchack+"', "
					    +"AckEtransNum="+POut.Long(etrans.EtransNum)
					    +" WHERE BatchNumber="+POut.Long(etrans.BatchNumber)
					    +" AND ClearinghouseNum="+POut.Long(hqClearinghouseNum)
					    +" AND DateTimeTrans > "+POut.DateT(dateTimeTrans.AddDays(-14))
					    +" AND DateTimeTrans < "+POut.DateT(dateTimeTrans.AddDays(1))
					    +" AND AckEtransNum=0";
					  Db.NonQ(command);
					}
					else {//partially accepted
					  List<int> transNums=x999.GetTransNums();
					  string ack;
					  for(int i=0;i<transNums.Count;i++) {
					    ack=x999.GetAckForTrans(transNums[i]);
					    if(ack=="A"||ack=="R") {//accepted or rejected
					      command="UPDATE etrans SET AckCode='"+ack+"', "
					        +"AckEtransNum="+POut.Long(etrans.EtransNum)
					        +" WHERE BatchNumber="+POut.Long(etrans.BatchNumber)
					        +" AND TransSetNum="+POut.Long(transNums[i])
					        +" AND ClearinghouseNum="+POut.Long(hqClearinghouseNum)
					        +" AND DateTimeTrans > "+POut.DateT(dateTimeTrans.AddDays(-14))
					        +" AND DateTimeTrans < "+POut.DateT(dateTimeTrans.AddDays(1))
					        +" AND AckEtransNum=0";
					      Db.NonQ(command);
					    }
					  }
					}
					//none of the other fields make sense, because this ack could refer to many claims.
				}
				else if(X277.Is277(Xobj)) {
					X277 x277=new X277(messageText);
					etrans.Etype=EtransType.StatusNotify_277;
					Etranss.Insert(etrans);
					List<string> listClaimIdentifiers=x277.GetClaimTrackingNumbers();
					//Dictionary to run one update command per ack code for many claims.
					Dictionary <string,List<X12ClaimMatch>> dictClaimMatchesByAck=new Dictionary<string,List<X12ClaimMatch>>();
					for(int i=0;i<listClaimIdentifiers.Count;i++) {
						X12ClaimMatch claimMatch=new X12ClaimMatch();
						claimMatch.ClaimIdentifier=listClaimIdentifiers[i];
						string[] arrayClaimInfo=x277.GetClaimInfo(claimMatch.ClaimIdentifier);
						claimMatch.PatFname=PIn.String(arrayClaimInfo[0]);
						claimMatch.PatLname=PIn.String(arrayClaimInfo[1]);
						claimMatch.DateServiceStart=PIn.DateT(arrayClaimInfo[6]);
						claimMatch.DateServiceEnd=PIn.DateT(arrayClaimInfo[7]);
						claimMatch.ClaimFee=PIn.Double(arrayClaimInfo[9]);
						claimMatch.SubscriberId=PIn.String(arrayClaimInfo[10]);
						claimMatch.EtransNum=etrans.EtransNum;
						string ack=arrayClaimInfo[3];
						if(!dictClaimMatchesByAck.ContainsKey(ack)) {
							dictClaimMatchesByAck.Add(ack,new List<X12ClaimMatch>());
						}
						dictClaimMatchesByAck[ack].Add(claimMatch);
					}
					foreach(string ack in dictClaimMatchesByAck.Keys) {
						List <long> listClaimNums=Claims.GetClaimFromX12(dictClaimMatchesByAck[ack]);
						if(listClaimNums!=null) {
							listClaimNums=listClaimNums.Where(x => x!=0).ToList();
							if(listClaimNums.Count > 0) {
								//Locate the latest etrans entries for the claims based on DateTimeTrans with EType of ClaimSent or Claim_Ren and update the AckCode and AckEtransNum.
								//We overwrite existing acks from 997s, 999s and older 277s.
								command="UPDATE etrans SET AckCode='"+ack+"', "
									+"AckEtransNum="+POut.Long(etrans.EtransNum)
									+" WHERE EType IN ("+POut.Int((int)EtransType.ClaimSent)+","+POut.Int((int)EtransType.Claim_Ren)+") "
									+" AND ClaimNum IN("+String.Join(",",listClaimNums.Select(x => POut.Long(x)))+")"
									+" AND ClearinghouseNum="+POut.Long(hqClearinghouseNum)
									+" AND DateTimeTrans > "+POut.DateT(dateTimeTrans.AddDays(-14))
									+" AND DateTimeTrans < "+POut.DateT(dateTimeTrans.AddDays(1));
								Db.NonQ(command);
							}
						}
						//none of the other fields make sense, because this ack could refer to many claims.
					}
				}
				else if(X835.Is835(Xobj)) {
					etrans.Etype=EtransType.ERA_835;
					List <string> listTranSetIds=Xobj.GetTranSetIds();
					List <Etrans> listEtrans=new List<Etrans>();
					List <X835> list835s=new List<X835>();
					//We pull in the 835 data in two loops so that we can ensure the 835 is fully parsed before we create any etrans entries.
					for(int i=0;i<listTranSetIds.Count;i++) {
						etrans.TranSetId835=listTranSetIds[i];
						if(i>0) {
							etrans.EtransNum=0;//To get a new record to insert.
						}
						X835 x835=new X835(etrans,messageText,etrans.TranSetId835);//parse. If parsing fails, then no etrans entries will be inserted.
						etrans.CarrierNameRaw=x835.PayerName;
						List<string> listUniquePatientNames=new List<string>();
						for(int j=0;j<x835.ListClaimsPaid.Count;j++) {
							string patName=x835.ListClaimsPaid[j].PatientName.ToString(false);
							if(!listUniquePatientNames.Contains(patName)) {
								listUniquePatientNames.Add(patName);
							}
						}
						if(listUniquePatientNames.Count==1) {
							etrans.PatientNameRaw=listUniquePatientNames[0];
						}
						else {
							etrans.PatientNameRaw="("+listUniquePatientNames.Count+" "+Lans.g("Etranss","patients")+")";
						}
						listEtrans.Add(etrans.Copy());
						list835s.Add(x835);
					}
					//The 835 was completely parsed.  Create etrans entries.
					for(int i=0;i<listEtrans.Count;i++) {
						etrans=listEtrans[i];
						X835 x835=list835s[i];
						Etranss.Insert(etrans);//insert
						List<long> listClaimNums=x835.ListClaimsPaid.Select(x => x.ClaimNum).Where(x => x!=0).ToList();
						if(listClaimNums.Count > 0) {
							//Locate the latest etrans entries for the claim based on DateTimeTrans with EType of ClaimSent or Claim_Ren and update the AckCode and AckEtransNum.
							//We overwrite existing acks from 997s, 999s, and 277s.
							command="UPDATE etrans SET AckCode='A', "
								+"AckEtransNum="+POut.Long(etrans.EtransNum)
								+" WHERE EType IN (0,3) "//ClaimSent and Claim_Ren
								+" AND ClaimNum IN("+String.Join(",",listClaimNums.Select(x => POut.Long(x)))+")"
								+" AND ClearinghouseNum="+POut.Long(hqClearinghouseNum)
								+" AND DateTimeTrans > "+POut.DateT(dateTimeTrans.AddDays(-14))
								+" AND DateTimeTrans < "+POut.DateT(dateTimeTrans.AddDays(1));
							Db.NonQ(command);
						}
						//none of the other fields make sense, because this ack could refer to many claims.
					}
				}
				else {//unknown type of X12 report.
					etrans.Etype=EtransType.TextReport;
					Etranss.Insert(etrans);
				}
			}
			else {//not X12
				etrans.Etype=EtransType.TextReport;
				Etranss.Insert(etrans);
			}
		}
Ejemplo n.º 5
0
		public static void Delete835(Etrans etrans) {
			EtransMessageTexts.Delete(etrans.EtransMessageTextNum,etrans.EtransNum);
			Etranss.Delete(etrans.EtransNum);
			Etrans835Attaches.DeleteMany(-1,etrans.EtransNum);
		}
Ejemplo n.º 6
0
        ///<summary>Takes any files found in the reports folder for the clearinghouse, and imports them into the database.
        ///Moves the original file into an Archive sub folder.
        ///Returns a string with any errors that occured.</summary>
        private static string ImportReportFiles(Clearinghouse clearinghouseClin, IODProgressExtended progress = null)        //uses clinic-level clearinghouse where necessary.
        {
            progress = progress ?? new ODProgressExtendedNull();
            if (!Directory.Exists(clearinghouseClin.ResponsePath))
            {
                return(Lans.g("FormClaimReports", "Report directory does not exist") + ": " + clearinghouseClin.ResponsePath);
            }
            if (clearinghouseClin.Eformat == ElectronicClaimFormat.Canadian || clearinghouseClin.Eformat == ElectronicClaimFormat.Ramq)
            {
                //the report path is shared with many other important files.  Do not process anything.  Comm is synchronous only.
                return("");
            }
            progress.UpdateProgress(Lans.g(progress.LanThis, "Reading download files"), "reports", "55%", 55);
            if (progress.IsPauseOrCancel())
            {
                return(Lans.g(progress.LanThis, "Import canceled by user."));
            }
            string[] files = null;
            string   archiveDir;

            try {
                files      = Directory.GetFiles(clearinghouseClin.ResponsePath);
                archiveDir = ODFileUtils.CombinePaths(clearinghouseClin.ResponsePath, "Archive" + "_" + DateTime.Now.Year.ToString());
                if (!Directory.Exists(archiveDir))
                {
                    Directory.CreateDirectory(archiveDir);
                }
            }
            catch (UnauthorizedAccessException ex) {
                ex.DoNothing();
                return(Lans.g("FormClaimReports", "Access to the Report Path is denied.  Try running as administrator or contact your network administrator."));
            }
            List <string> listFailedFiles = new List <string>();

            progress.UpdateProgress(Lans.g(progress.LanThis, "Files read."));
            progress.UpdateProgress(Lans.g(progress.LanThis, "Importing files"), "reports", "83%", 83);
            if (files.Length > 0)
            {
                progress.UpdateProgressDetailed(Lans.g(progress.LanThis, "Importing"), tagString: "import");             //add a new progress bar for imports if there are any to import
            }
            else
            {
                progress.UpdateProgress(Lans.g(progress.LanThis, "No files to import."));
            }
            for (int i = 0; i < files.Length; i++)
            {
                int percent = (i / files.Length) * 100;
                progress.UpdateProgress(Lans.g(progress.LanThis, "Importing") + " " + i + " / " + files.Length, "import", percent + "%", percent);
                if (progress.IsPauseOrCancel())
                {
                    return(Lans.g(progress.LanThis, "Import canceled by user."));
                }
                string fileSource      = files[i];
                string fileDestination = ODFileUtils.CombinePaths(archiveDir, Path.GetFileName(files[i]));
                try {
                    File.Move(fileSource, fileDestination);
                }
                catch (Exception ex) {
                    ex.DoNothing();              //OK to continue, since ProcessIncomingReport() above saved the raw report into the etrans table.
                    listFailedFiles.Add(fileSource);
                    continue;                    //Skip current report file and leave in folder to processing later.
                }
                try {
                    Etranss.ProcessIncomingReport(
                        File.GetCreationTime(fileDestination),
                        clearinghouseClin.HqClearinghouseNum,
                        File.ReadAllText(fileDestination),
                        Security.CurUser.UserNum);
                }
                catch (Exception ex) {
                    ex.DoNothing();
                    listFailedFiles.Add(fileSource);
                    File.Move(fileDestination, fileSource);                   //Move file back so that the archived folder only contains succesfully processed reports.
                }
            }
            if (listFailedFiles.Count > 0)
            {
                return(Lans.g("FormClaimReports", "Failed to process the following files due to permission issues or malformed data")
                       + ":\r\n" + string.Join(",\r\n", listFailedFiles));
            }
            return("");
        }
Ejemplo n.º 7
0
        ///<summary>Returns a blank string if there were no errors while attempting to update internal carriers using iTrans n-cpl.json file..</summary>
        public static string TryCarrierUpdate(bool isAutomatic = true, ItransImportFields fieldsToImport = ItransImportFields.None)
        {
            Clearinghouse clearinghouse = Clearinghouses.GetDefaultDental();

            if (clearinghouse.CommBridge != EclaimsCommBridge.ITRANS ||
                string.IsNullOrEmpty(clearinghouse.ResponsePath) ||
                !File.Exists(ODFileUtils.CombinePaths(clearinghouse.ResponsePath, "ITRANS Claims Director.exe")) ||
                (isAutomatic && PrefC.GetString(PrefName.WebServiceServerName).ToLower() != Dns.GetHostName().ToLower()))                 //Only server can run when isOnlyServer is true.
            {
                return(Lans.g("Clearinghouse", "ITRANS must be the default dental clearinghouse and your Report Path must be set first."));
            }
            Process process = new Process {
                StartInfo = new ProcessStartInfo {
                    FileName  = ODFileUtils.CombinePaths(clearinghouse.ResponsePath, "ITRANS Claims Director.exe"),
                    Arguments = " --getncpl"
                }
            };

            process.Start();
            process.WaitForExit();
            string            ncplFilePath = ODFileUtils.CombinePaths(clearinghouse.ResponsePath, "n-cpl.json");
            string            json         = File.ReadAllText(ncplFilePath);//Read n-cpl.json
            EtransMessageText msgTextPrev  = EtransMessageTexts.GetMostRecentForType(EtransType.ItransNcpl);

            if (msgTextPrev != null && msgTextPrev.MessageText == json)
            {
                return(Lans.g("Clearinghouse", "Carrier list has not changed since last checked."));              //json has not changed since we last checked, no need to update.
            }
            //Save json as new etrans entry.
            Etrans etrans = Etranss.CreateEtrans(File.GetCreationTime(ncplFilePath), clearinghouse.HqClearinghouseNum, json, 0);

            etrans.Etype = EtransType.ItransNcpl;
            Etranss.Insert(etrans);
            ItransNCpl iTransNCpl = null;

            try {
                iTransNCpl = JsonConvert.DeserializeObject <ItransNCpl>(json);             //Deserialize n-cpl.json
            }
            catch (Exception ex) {
                ex.DoNothing();
                return(Lans.g("Clearinghouse", "Failed to import json."));
            }
            foreach (ItransNCpl.Carrier jsonCarrier in iTransNCpl.ListCarriers)              //Update providers.
            {
                OpenDentBusiness.Carrier odCarrier = Carriers.GetByElectId(jsonCarrier.Bin); //Cached
                if (odCarrier == null)                                                       //Carrier can not be matched to internal Carrier based on ElectID.
                {
                    if (!fieldsToImport.HasFlag(ItransImportFields.AddMissing))
                    {
                        continue;
                    }
                    OpenDentBusiness.Carrier carrierNew = new OpenDentBusiness.Carrier();
                    carrierNew.ElectID     = jsonCarrier.Bin;
                    carrierNew.IsCDA       = true;
                    carrierNew.CarrierName = jsonCarrier.Name.En;
                    carrierNew.Phone       = TelephoneNumbers.ReFormat(jsonCarrier.Telephone?.First().Value);
                    if (jsonCarrier.Address.Count() > 0)
                    {
                        Address add = jsonCarrier.Address.First();
                        carrierNew.Address  = add.Street1;
                        carrierNew.Address2 = add.Street2;
                        carrierNew.City     = add.City;
                        carrierNew.State    = add.Province;
                        carrierNew.Zip      = add.PostalCode;
                    }
                    carrierNew.CanadianSupportedTypes = GetSupportedTypes(jsonCarrier);
                    carrierNew.CarrierName            = jsonCarrier.Name.En;
                    try {
                        Carriers.Insert(carrierNew);
                    }
                    catch (Exception ex) {
                        ex.DoNothing();
                    }
                    continue;
                }
                else if (!odCarrier.IsCDA)
                {
                    continue;
                }
                OpenDentBusiness.Carrier odCarrierOld = odCarrier.Copy();
                odCarrier.CanadianSupportedTypes = GetSupportedTypes(jsonCarrier);
                odCarrier.CDAnetVersion          = POut.Int(jsonCarrier.Versions.Max(x => PIn.Int(x)));
                List <ItransImportFields> listFields = Enum.GetValues(typeof(ItransImportFields)).Cast <ItransImportFields>().ToList();
                foreach (ItransImportFields field in listFields)
                {
                    if (fieldsToImport == ItransImportFields.None)
                    {
                        break;                        //No point in looping.
                    }
                    if (field == ItransImportFields.None || !fieldsToImport.HasFlag(field))
                    {
                        continue;
                    }
                    switch (field)
                    {
                    case ItransImportFields.Phone:
                        if (jsonCarrier.Telephone.Count > 0)
                        {
                            odCarrier.Phone = TelephoneNumbers.ReFormat(jsonCarrier.Telephone.First().Value);
                        }
                        break;

                    case ItransImportFields.Address:
                        if (jsonCarrier.Address.Count() > 0)
                        {
                            Address add = jsonCarrier.Address.First();
                            odCarrier.Address  = add.Street1;
                            odCarrier.Address2 = add.Street2;
                            odCarrier.City     = add.City;
                            odCarrier.State    = add.Province;
                            odCarrier.Zip      = add.PostalCode;
                        }
                        break;

                    case ItransImportFields.Name:
                        odCarrier.CarrierName = jsonCarrier.Name.En;
                        break;
                    }
                }
                try {
                    long userNum = 0;
                    if (!isAutomatic)
                    {
                        userNum = Security.CurUser.UserNum;
                    }
                    Carriers.Update(odCarrier, odCarrierOld, userNum);
                }
                catch (Exception ex) {
                    ex.DoNothing();
                }
            }
            return("");           //Blank string represents a completed update.
        }
Ejemplo n.º 8
0
        ///<summary>Etrans type will be figured out by this class.  Either TextReport, Acknowledge_997, or StatusNotify_277.</summary>
        public static void ProcessIncomingReport(DateTime dateTimeTrans, long clearinghouseNum, string messageText)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                Meth.GetVoid(MethodBase.GetCurrentMethod(), dateTimeTrans, clearinghouseNum, messageText);
                return;
            }
            Etrans etrans = new Etrans();

            etrans.DateTimeTrans    = dateTimeTrans;
            etrans.ClearingHouseNum = clearinghouseNum;
            EtransMessageText etransMessageText = new EtransMessageText();

            etransMessageText.MessageText = messageText;
            EtransMessageTexts.Insert(etransMessageText);
            etrans.EtransMessageTextNum = etransMessageText.EtransMessageTextNum;
            string command;

            if (X12object.IsX12(messageText))
            {
                X12object Xobj = new X12object(messageText);
                if (Xobj.Is997())
                {
                    X997 x997 = new X997(messageText);
                    etrans.Etype       = EtransType.Acknowledge_997;
                    etrans.BatchNumber = x997.GetBatchNumber();
                    Etranss.Insert(etrans);
                    string batchack = x997.GetBatchAckCode();
                    if (batchack == "A" || batchack == "R")               //accepted or rejected
                    {
                        command = "UPDATE etrans SET AckCode='" + batchack + "', "
                                  + "AckEtransNum=" + POut.Long(etrans.EtransNum)
                                  + " WHERE BatchNumber=" + POut.Long(etrans.BatchNumber)
                                  + " AND ClearinghouseNum=" + POut.Long(clearinghouseNum)
                                  + " AND DateTimeTrans > " + POut.DateT(dateTimeTrans.AddDays(-14))
                                  + " AND DateTimeTrans < " + POut.DateT(dateTimeTrans.AddDays(1))
                                  + " AND AckEtransNum=0";
                        Db.NonQ(command);
                    }
                    else                      //partially accepted
                    {
                        List <int> transNums = x997.GetTransNums();
                        string     ack;
                        for (int i = 0; i < transNums.Count; i++)
                        {
                            ack = x997.GetAckForTrans(transNums[i]);
                            if (ack == "A" || ack == "R")                       //accepted or rejected
                            {
                                command = "UPDATE etrans SET AckCode='" + ack + "', "
                                          + "AckEtransNum=" + POut.Long(etrans.EtransNum)
                                          + " WHERE BatchNumber=" + POut.Long(etrans.BatchNumber)
                                          + " AND TransSetNum=" + POut.Long(transNums[i])
                                          + " AND ClearinghouseNum=" + POut.Long(clearinghouseNum)
                                          + " AND DateTimeTrans > " + POut.DateT(dateTimeTrans.AddDays(-14))
                                          + " AND DateTimeTrans < " + POut.DateT(dateTimeTrans.AddDays(1))
                                          + " AND AckEtransNum=0";
                                Db.NonQ(command);
                            }
                        }
                    }
                    //none of the other fields make sense, because this ack could refer to many claims.
                }
                else if (X277U.Is277U(Xobj))
                {
                    etrans.Etype = EtransType.StatusNotify_277;
                    //later: analyze to figure out which e-claim is being referenced.
                    Etranss.Insert(etrans);
                }
                else                  //unknown type of X12 report.
                {
                    etrans.Etype = EtransType.TextReport;
                    Etranss.Insert(etrans);
                }
            }
            else              //not X12
            {
                etrans.Etype = EtransType.TextReport;
                Etranss.Insert(etrans);
            }
        }