コード例 #1
0
ファイル: Etranss.cs プロジェクト: ChemBrain/OpenDental
		///<summary></summary>
		public static void Update(Etrans etrans) {
			if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
				Meth.GetVoid(MethodBase.GetCurrentMethod(),etrans);
				return;
			}
			Crud.EtransCrud.Update(etrans);
		}
コード例 #2
0
ファイル: Etranss.cs プロジェクト: ChemBrain/OpenDental
		///<summary>Returns an etrans that has not been inserted into the DB.
		///Should only be called with etrans is related an EtransType that is of claim type, currently no validation is done in this function to ensure this.</summary>
		public static Etrans CreateEtransForClaim(long claimNum,long patNum,long clearinghouseNum,EtransType etype,int batchNumber,long userNum) {
			if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
				return Meth.GetObject<Etrans>(MethodBase.GetCurrentMethod(),claimNum,patNum,clearinghouseNum,etype,batchNumber,userNum);
			}
			Etrans etrans=new Etrans();
			//etrans.DateTimeTrans handled automatically
			etrans.ClearingHouseNum=clearinghouseNum;
			etrans.Etype=etype;
			etrans.ClaimNum=claimNum;
			etrans.PatNum=patNum;
			etrans.UserNum=userNum;
			//Get the primary and secondary carrierNums for this claim.
			string 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);
			if(table.Rows.Count > 0) {//The claim could have been deleted by someone else.  Don't worry about preserving the carrier information.  Set to 0.
				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
			}
			else {
				etrans.Note=Lans.g(nameof(Etrans),"Primry carrier and secondary carrier are unknown due to missing claim.  Invalid ClaimNum.  "
					+"Claim may have been deleted during sending.");
			}
			etrans.BatchNumber=batchNumber;
			return etrans;
		}
コード例 #3
0
ファイル: Etranss.cs プロジェクト: ChemBrain/OpenDental
		///<summary>Not for claim types, just other types, including Eligibility. This function gets run first.  Then, the messagetext is created and an attempt is made to send the message.  Finally, the messagetext is added to the etrans.  This is necessary because the transaction numbers must be incremented and assigned to each message before creating the message and attempting to send.  If it fails, we will need to roll back.  Provide EITHER a carrierNum OR a canadianNetworkNum.  Many transactions can be sent to a carrier or to a network.</summary>
		public static Etrans CreateCanadianOutput(long patNum,long carrierNum,long canadianNetworkNum
			,long clearinghouseNum,EtransType etype,long planNum,long insSubNum,long userNum,bool hasSecondary=false)
		{
			if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
				return Meth.GetObject<Etrans>(MethodBase.GetCurrentMethod(),patNum,carrierNum,canadianNetworkNum,clearinghouseNum,etype,planNum,insSubNum,userNum,hasSecondary);
			}
			//validation of carrier vs network
			if(etype==EtransType.Eligibility_CA){
				//only carrierNum is allowed (and required)
				if(carrierNum==0){
					throw new ApplicationException("Carrier not supplied for Etranss.CreateCanadianOutput.");
				}
				if(canadianNetworkNum!=0){
					throw new ApplicationException("NetworkNum not allowed for Etranss.CreateCanadianOutput.");
				}
			}
			Etrans etrans=new Etrans();
			//etrans.DateTimeTrans handled automatically
			etrans.ClearingHouseNum=clearinghouseNum;
			etrans.Etype=etype;
			etrans.ClaimNum=0;//no claim involved
			etrans.PatNum=patNum;
			//CanadianNetworkNum?
			etrans.CarrierNum=carrierNum;
			etrans.PlanNum=planNum;
			etrans.InsSubNum=insSubNum;
			etrans.UserNum=userNum;
			etrans.BatchNumber=0;
			//Get next OfficeSequenceNumber-----------------------------------------------------------------------------------------
			etrans=SetCanadianEtransFields(etrans,hasSecondary);
			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.
		}
コード例 #4
0
ファイル: Etranss.cs プロジェクト: ChemBrain/OpenDental
		/*
		///<summary></summary>
		public static Etrans GetAckForTrans(int etransNum) {
			if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
				return Meth.GetObject<Etrans>(MethodBase.GetCurrentMethod(),etransNum);
			}
			//first, get the actual trans.
			string command="SELECT * FROM etrans WHERE EtransNum="+POut.PInt(etransNum);
			DataTable table=Db.GetTable(command);
			Etrans etrans=SubmitAndFill(table);
			command="SELECT * FROM etrans WHERE "
				+"Etype=21 "//ack997
				+"AND ClearingHouseNum="+POut.PInt(etrans.ClearingHouseNum)
				+" AND BatchNumber= "+POut.PInt(etrans.BatchNumber)
				+" AND DateTimeTrans < "+POut.PDateT(etrans.DateTimeTrans.AddDays(14))//less than 2wks in the future
				+" AND DateTimeTrans > "+POut.PDateT(etrans.DateTimeTrans.AddDays(-1));//and no more than one day before claim
			table=Db.GetTable(command);
			return SubmitAndFill(table);
		}*/

		/*
		private static List<Etrans> SubmitAndFill(DataTable table){
			//No need to check RemotingRole; no call to db.
			//if(table.Rows.Count==0){
			//	return null;
			//}
			List<Etrans> retVal=new List<Etrans>();
			Etrans etrans;
			for(int i=0;i<table.Rows.Count;i++) {
				etrans=new Etrans();
				etrans.EtransNum           =PIn.Long(table.Rows[i][0].ToString());
				etrans.DateTimeTrans       =PIn.DateT(table.Rows[i][1].ToString());
				etrans.ClearingHouseNum    =PIn.Long(table.Rows[i][2].ToString());
				etrans.Etype               =(EtransType)PIn.Long(table.Rows[i][3].ToString());
				etrans.ClaimNum            =PIn.Long(table.Rows[i][4].ToString());
				etrans.OfficeSequenceNumber=PIn.Int(table.Rows[i][5].ToString());
				etrans.CarrierTransCounter =PIn.Int(table.Rows[i][6].ToString());
				etrans.CarrierTransCounter2=PIn.Int(table.Rows[i][7].ToString());
				etrans.CarrierNum          =PIn.Long(table.Rows[i][8].ToString());
				etrans.CarrierNum2         =PIn.Long(table.Rows[i][9].ToString());
				etrans.PatNum              =PIn.Long(table.Rows[i][10].ToString());
				etrans.BatchNumber         =PIn.Int(table.Rows[i][11].ToString());
				etrans.AckCode             =PIn.String(table.Rows[i][12].ToString());
				etrans.TransSetNum         =PIn.Int(table.Rows[i][13].ToString());
				etrans.Note                =PIn.String(table.Rows[i][14].ToString());
				etrans.EtransMessageTextNum=PIn.Long(table.Rows[i][15].ToString());
				etrans.AckEtransNum        =PIn.Long(table.Rows[i][16].ToString());
				etrans.PlanNum             =PIn.Long(table.Rows[i][17].ToString());
				retVal.Add(etrans);
			}
			return retVal;
		}*/

		///<summary>DateTimeTrans handled automatically here.</summary>
		public static long Insert(Etrans etrans) {
			if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
				etrans.EtransNum=Meth.GetLong(MethodBase.GetCurrentMethod(),etrans);
				return etrans.EtransNum;
			}
			return Crud.EtransCrud.Insert(etrans);
		}
コード例 #5
0
		private void FormEtrans270Edit_Load(object sender,EventArgs e) {
			MessageText=EtransMessageTexts.GetMessageText(EtransCur.EtransMessageTextNum);
			MessageTextAck="";
			//textMessageText.Text=MessageText;
			textNote.Text=EtransCur.Note;
			EtransAck271=Etranss.GetEtrans(EtransCur.AckEtransNum);
			x271=null;
			if(EtransAck271!=null) {
				MessageTextAck=EtransMessageTexts.GetMessageText(EtransAck271.EtransMessageTextNum);//.Replace("~","~\r\n");
				if(EtransAck271.Etype==EtransType.BenefitResponse271) {
					x271=new X271(MessageTextAck);
				}
			}
			listDTP=new List<DTP271>();
			if(x271 != null) {
				listDTP=x271.GetListDtpSubscriber();
			}
			FillGridDates();
			CreateListOfBenefits();
			FillGrid();
			FillGridBen();
			if(IsInitialResponse) {
				SelectForImport();
			}
		}
コード例 #6
0
		///<summary>Called externally to display and/or print the messageText as a form.</summary>
		public FormCCDPrint(Etrans pEtrans,string messageText,bool pAutoPrint) {
			etrans=pEtrans;
			MessageText=messageText;
			copiesToPrint=0;
			autoPrint=pAutoPrint;
			Init();
		}
コード例 #7
0
ファイル: FormEtrans835PickEob.cs プロジェクト: mnisl/OD
		public FormEtrans835PickEob(List <string> listEobTranIds,string messageText835,Etrans etrans) {
			InitializeComponent();
			Lan.F(this);
			_listEobTranIds=listEobTranIds;
			_messageText835=messageText835;
			_etrans=etrans;
		}
コード例 #8
0
ファイル: Etranss.cs プロジェクト: ChemBrain/OpenDental
		///<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,long userNum) {
			if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
				return Meth.GetObject<Etrans>(MethodBase.GetCurrentMethod(),claimNum,patNum,clearinghouseNum,etype,batchNumber,userNum);
			}
			Etrans etrans=CreateEtransForClaim(claimNum,patNum,clearinghouseNum,etype,batchNumber,userNum);
			etrans=SetCanadianEtransFields(etrans);//etrans.CarrierNum, etrans.CarrierNum2 and etrans.EType all set prior to calling this.
			Claims.SetClaimSent(claimNum);
			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.
		}
コード例 #9
0
ファイル: Etranss.cs プロジェクト: ChemBrain/OpenDental
		///<summary>Creates new etrans object, does not insert to Etrans table though. Does insert EtransMessageText.</summary>
		public static Etrans CreateEtrans(DateTime dateTimeTrans,long hqClearinghouseNum,string messageText,long userNum){
			Etrans etrans=new Etrans();
			etrans.DateTimeTrans=dateTimeTrans;
			etrans.ClearingHouseNum=hqClearinghouseNum;
			EtransMessageText etransMessageText=new EtransMessageText();
			etransMessageText.MessageText=messageText;
			EtransMessageTexts.Insert(etransMessageText);
			etrans.EtransMessageTextNum=etransMessageText.EtransMessageTextNum;
			etrans.UserNum=userNum;
			return etrans;
		}
コード例 #10
0
        ///<summary></summary>
        public Etrans Copy()
        {
            Etrans e = new Etrans();

            e.EtransNum            = EtransNum;
            e.DateTimeTrans        = DateTimeTrans;
            e.ClearinghouseNum     = ClearinghouseNum;
            e.Etype                = Etype;
            e.ClaimNum             = ClaimNum;
            e.OfficeSequenceNumber = OfficeSequenceNumber;
            e.CarrierTransCounter  = CarrierTransCounter;
            e.CarrierTransCounter2 = CarrierTransCounter2;
            e.CarrierNum           = CarrierNum;
            e.CarrierNum2          = CarrierNum2;
            e.PatNum               = PatNum;
            e.MessageText          = MessageText;
            return(e);
        }
コード例 #11
0
ファイル: Etranss.cs プロジェクト: nampn/ODental
 /*
 ///<summary></summary>
 public static Etrans GetAckForTrans(int etransNum) {
     if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
         return Meth.GetObject<Etrans>(MethodBase.GetCurrentMethod(),etransNum);
     }
     //first, get the actual trans.
     string command="SELECT * FROM etrans WHERE EtransNum="+POut.PInt(etransNum);
     DataTable table=Db.GetTable(command);
     Etrans etrans=SubmitAndFill(table);
     command="SELECT * FROM etrans WHERE "
         +"Etype=21 "//ack997
         +"AND ClearingHouseNum="+POut.PInt(etrans.ClearingHouseNum)
         +" AND BatchNumber= "+POut.PInt(etrans.BatchNumber)
         +" AND DateTimeTrans < "+POut.PDateT(etrans.DateTimeTrans.AddDays(14))//less than 2wks in the future
         +" AND DateTimeTrans > "+POut.PDateT(etrans.DateTimeTrans.AddDays(-1));//and no more than one day before claim
     table=Db.GetTable(command);
     return SubmitAndFill(table);
 }*/
 /*
 private static List<Etrans> SubmitAndFill(DataTable table){
     //No need to check RemotingRole; no call to db.
     //if(table.Rows.Count==0){
     //	return null;
     //}
     List<Etrans> retVal=new List<Etrans>();
     Etrans etrans;
     for(int i=0;i<table.Rows.Count;i++) {
         etrans=new Etrans();
         etrans.EtransNum           =PIn.Long(table.Rows[i][0].ToString());
         etrans.DateTimeTrans       =PIn.DateT(table.Rows[i][1].ToString());
         etrans.ClearingHouseNum    =PIn.Long(table.Rows[i][2].ToString());
         etrans.Etype               =(EtransType)PIn.Long(table.Rows[i][3].ToString());
         etrans.ClaimNum            =PIn.Long(table.Rows[i][4].ToString());
         etrans.OfficeSequenceNumber=PIn.Int(table.Rows[i][5].ToString());
         etrans.CarrierTransCounter =PIn.Int(table.Rows[i][6].ToString());
         etrans.CarrierTransCounter2=PIn.Int(table.Rows[i][7].ToString());
         etrans.CarrierNum          =PIn.Long(table.Rows[i][8].ToString());
         etrans.CarrierNum2         =PIn.Long(table.Rows[i][9].ToString());
         etrans.PatNum              =PIn.Long(table.Rows[i][10].ToString());
         etrans.BatchNumber         =PIn.Int(table.Rows[i][11].ToString());
         etrans.AckCode             =PIn.String(table.Rows[i][12].ToString());
         etrans.TransSetNum         =PIn.Int(table.Rows[i][13].ToString());
         etrans.Note                =PIn.String(table.Rows[i][14].ToString());
         etrans.EtransMessageTextNum=PIn.Long(table.Rows[i][15].ToString());
         etrans.AckEtransNum        =PIn.Long(table.Rows[i][16].ToString());
         etrans.PlanNum             =PIn.Long(table.Rows[i][17].ToString());
         retVal.Add(etrans);
     }
     return retVal;
 }*/
 ///<summary>DateTimeTrans handled automatically here.</summary>
 public static long Insert(Etrans etrans)
 {
     if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
         etrans.EtransNum=Meth.GetLong(MethodBase.GetCurrentMethod(),etrans);
         return etrans.EtransNum;
     }
     return Crud.EtransCrud.Insert(etrans);
 }
コード例 #12
0
ファイル: Etranss.cs プロジェクト: nampn/ODental
 ///<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);
     }
 }
コード例 #13
0
ファイル: CanadianOutput.cs プロジェクト: nampn/ODental
 ///<summary>The result is the etransNum of the response message.  Or it might throw an exception if invalid data.  This class is also responsible for saving the returned message to the etrans table, and for printing out the required form.</summary>
 public static long SendElegibility(long patNum,InsPlan plan,DateTime date,Relat relat,string patID,bool doPrint,InsSub insSub)
 {
     //string electID,long patNum,string groupNumber,string divisionNo,
     //string subscriberID,string patID,Relat patRelat,long subscNum,string dentaideCardSequence)
     //Note: This might be the only class of this kind that returns a string.  It's a special situation.
     //We are simply not going to bother with language translation here.
     Carrier carrier=Carriers.GetCarrier(plan.CarrierNum);
     if(carrier==null) {
         throw new ApplicationException("Invalid carrier.");
     }
     if((carrier.CanadianSupportedTypes&CanSupTransTypes.EligibilityTransaction_08)!=CanSupTransTypes.EligibilityTransaction_08) {
         throw new ApplicationException("The carrier does not support eligibility transactions.");
     }
     if(carrier.CanadianNetworkNum==0) {
         throw new ApplicationException("Carrier network not set.");
     }
     CanadianNetwork network=CanadianNetworks.GetNetwork(carrier.CanadianNetworkNum);
     Patient patient=Patients.GetPat(patNum);
     Patient subscriber=Patients.GetPat(insSub.Subscriber);
     Provider provDefaultTreat=Providers.GetProv(PrefC.GetLong(PrefName.PracticeDefaultProv));
     Clearinghouse clearhouse=Canadian.GetClearinghouse();
     if(clearhouse==null){
         throw new ApplicationException("Canadian clearinghouse not found.");
     }
     string saveFolder=clearhouse.ExportPath;
     if(!Directory.Exists(saveFolder)) {
         throw new ApplicationException(saveFolder+" not found.");
     }
     //validate----------------------------------------------------------------------------------------------------
     string error="";
     //if(carrier.CanadianNetworkNum==0){
     //	if(error!="") error+=", ";
     //	error+="Carrier does not have network specified";
     //}
     if(!Regex.IsMatch(carrier.ElectID,@"^[0-9]{6}$")){//not necessary, but nice
         if(error!="") error+=", ";
         error+="CarrierId 6 digits";
     }
     if(!provDefaultTreat.IsCDAnet) {
         error+="Prov not setup as CDA provider";
     }
     if(provDefaultTreat.NationalProvID.Length!=9) {
         if(error!="")	error+=", ";
         error+="Prov CDA num 9 digits";
     }
     if(provDefaultTreat.CanadianOfficeNum.Length!=4) {
         if(error!="") error+=", ";
         error+="Prov office num 4 char";
     }
     //if(plan.GroupNum.Length==0 || groupNumber.Length>12 || groupNumber.Contains(" ")){
     //	if(error!="") error+=", ";
     //	error+="Plan Number";
     //}
     //if(subscriberID==""){//already validated.  And it's allowed to be blank sometimes
     //	if(error!="") error+=", ";
     //	error+="SubscriberID";
     //}
     if(patNum != insSub.Subscriber && relat==Relat.Self) {//if patient is not subscriber, and relat is self
         if(error!="") error+=", ";
         error+="Relationship cannot be self";
     }
     if(patient.Gender==PatientGender.Unknown){
         if(error!="") error+=", ";
         error+="Patient gender";
     }
     if(patient.Birthdate.Year<1880 || patient.Birthdate>DateTime.Today) {
         if(error!="") error+=", ";
         error+="Patient birthdate";
     }
     if(patient.LName=="") {
         if(error!="") error+=", ";
         error+="Patient lastname";
     }
     if(patient.FName=="") {
         if(error!="") error+=", ";
         error+="Patient firstname";
     }
     if(patient.CanadianEligibilityCode==0) {
         if(error!="") error+=", ";
         error+="Patient eligibility exception code";
     }
     if(subscriber.Birthdate.Year<1880 || subscriber.Birthdate>DateTime.Today) {
         if(error!="") error+=", ";
         error+="Subscriber birthdate";
     }
     if(subscriber.LName=="") {
         if(error!="") error+=", ";
         error+="Subscriber lastname";
     }
     if(subscriber.FName=="") {
         if(error!="") error+=", ";
         error+="Subscriber firstname";
     }
     if(error!="") {
         throw new ApplicationException(error);
     }
     Etrans etrans=Etranss.CreateCanadianOutput(patNum,carrier.CarrierNum,0,
         clearhouse.ClearinghouseNum,EtransType.Eligibility_CA,plan.PlanNum,insSub.InsSubNum);
     StringBuilder strb=new StringBuilder();
     //create message----------------------------------------------------------------------------------------------
     //A01 transaction prefix 12 AN
     strb.Append(Canadian.TidyAN(network.CanadianTransactionPrefix,12));
     //A02 office sequence number 6 N
     strb.Append(Canadian.TidyN(etrans.OfficeSequenceNumber,6));
     //A03 format version number 2 N
     strb.Append(carrier.CDAnetVersion);//eg. "04", validated in UI
     //A04 transaction code 2 N
     if(carrier.CDAnetVersion=="02"){
         strb.Append("00");//eligibility
     }
     else{
         strb.Append("08");//eligibility
     }
     //A05 carrier id number 6 N
     strb.Append(carrier.ElectID);//already validated as 6 digit number.
     //A06 software system id 3 AN
     strb.Append(Canadian.SoftwareSystemId());
     if(carrier.CDAnetVersion=="04") {
         //A10 encryption method 1 N
         strb.Append(carrier.CanadianEncryptionMethod);//validated in UI
     }
     //A07 message length 5 N
     int len;
     bool C19PlanRecordPresent=false;
     if(carrier.CDAnetVersion=="02"){
         len=178;
         strb.Append(Canadian.TidyN(len,4));
     }
     else{
         len=214;
         if(plan.CanadianPlanFlag=="A"){// || plan.CanadianPlanFlag=="N"){
             C19PlanRecordPresent=true;
         }
         if(C19PlanRecordPresent){
             len+=30;
         }
         strb.Append(Canadian.TidyN(len,5));
         //A09 carrier transaction counter 5 N, only version 04
         strb.Append(Canadian.TidyN(etrans.CarrierTransCounter,5));
     }
     //B01 CDA provider number 9 AN
     strb.Append(Canadian.TidyAN(provDefaultTreat.NationalProvID,9));//already validated
     //B02 provider office number 4 AN
     strb.Append(Canadian.TidyAN(provDefaultTreat.CanadianOfficeNum,4));//already validated
     if(carrier.CDAnetVersion=="04"){
         //B03 billing provider number 9 AN
         Provider provBilling=Providers.GetProv(Providers.GetBillingProvNum(provDefaultTreat.ProvNum,patient.ClinicNum));
         strb.Append(Canadian.TidyAN(provBilling.NationalProvID,9));//already validated
     }
     if(carrier.CDAnetVersion=="02") {
         //C01 primary policy/plan number 8 AN (group number)
         //No special validation for version 02
         strb.Append(Canadian.TidyAN(plan.GroupNum,8));
     }
     else {
         //C01 primary policy/plan number 12 AN (group number)
         //only validated to ensure that it's not blank and is less than 12. Also that no spaces.
         strb.Append(Canadian.TidyAN(plan.GroupNum,12));
     }
     //C11 primary division/section number 10 AN
     strb.Append(Canadian.TidyAN(plan.DivisionNo,10));
     if(carrier.CDAnetVersion=="02") {
         //C02 subscriber id number 11 AN
         strb.Append(Canadian.TidyAN(insSub.SubscriberID.Replace("-",""),11));//no extra validation for version 02
     }
     else{
         //C02 subscriber id number 12 AN
         strb.Append(Canadian.TidyAN(insSub.SubscriberID.Replace("-",""),12));//validated
     }
     if(carrier.CDAnetVersion=="04") {
         //C17 primary dependant code 2 N. Optional
         strb.Append(Canadian.TidyN(patID,2));
     }
     //C03 relationship code 1 N
     //User interface does not only show Canadian options, but all options are handled.
     strb.Append(Canadian.GetRelationshipCode(relat));
     //C04 patient's sex 1 A
     //validated to not include "unknown"
     if(patient.Gender==PatientGender.Male) {
         strb.Append("M");
     }
     else {
         strb.Append("F");
     }
     //C05 patient birthday 8 N
     strb.Append(patient.Birthdate.ToString("yyyyMMdd"));//validated
     //C06 patient last name 25 AE
     strb.Append(Canadian.TidyAE(patient.LName,25,true));//validated
     //C07 patient first name 15 AE
     strb.Append(Canadian.TidyAE(patient.FName,15,true));//validated
     //C08 patient middle initial 1 AE
     strb.Append(Canadian.TidyAE(patient.MiddleI,1));
     //C09 eligibility exception code 1 N
     strb.Append(Canadian.GetEligibilityCode(patient.CanadianEligibilityCode,carrier.CDAnetVersion=="02"));//validated
     if(carrier.CDAnetVersion=="04") {
         //C12 plan flag 1 A
         strb.Append(Canadian.GetPlanFlag(plan.CanadianPlanFlag));
         //C18 plan record count 1 N
         if(C19PlanRecordPresent) {
             strb.Append("1");
         }
         else {
             strb.Append("0");
         }
         //C16 Eligibility date. 8 N.
         strb.Append(date.ToString("yyyyMMdd"));
     }
     //D01 subscriber birthday 8 N
     strb.Append(subscriber.Birthdate.ToString("yyyyMMdd"));//validated
     //D02 subscriber last name 25 AE
     strb.Append(Canadian.TidyAE(subscriber.LName,25,true));//validated
     //D03 subscriber first name 15 AE
     strb.Append(Canadian.TidyAE(subscriber.FName,15,true));//validated
     //D04 subscriber middle initial 1 AE
     strb.Append(Canadian.TidyAE(subscriber.MiddleI,1));
     if(carrier.CDAnetVersion=="04") {
         //D10 language of insured 1 A
         if(subscriber.Language=="fr") {
             strb.Append("F");
         }
         else {
             strb.Append("E");
         }
         //D11 card sequence/version number 2 N
         //Not validated against type of carrier.  Might need to check if Dentaide.
         strb.Append(Canadian.TidyN(plan.DentaideCardSequence,2));
         //C19 plan record 30 AN
         if(C19PlanRecordPresent) {
             //todo: what text goes here?  Not documented
             strb.Append(Canadian.TidyAN("",30));
         }
     }
     string result="";
     bool resultIsError=false;
     try {
         result=Canadian.PassToIca(strb.ToString(),clearhouse);
     }
     catch(ApplicationException ex) {
         result=ex.Message;
         resultIsError=true;
         //Etranss.Delete(etrans.EtransNum);//we don't want to do this, because we want the incremented etrans.OfficeSequenceNumber to be saved
         //Attach an ack indicating failure.
     }
     //Attach an ack to the etrans
     Etrans etransAck=new Etrans();
     etransAck.PatNum=etrans.PatNum;
     etransAck.PlanNum=etrans.PlanNum;
     etransAck.InsSubNum=etrans.InsSubNum;
     etransAck.CarrierNum=etrans.CarrierNum;
     etransAck.DateTimeTrans=DateTime.Now;
     CCDFieldInputter fieldInputter=null;
     if(resultIsError){
         etransAck.Etype=EtransType.AckError;
         etrans.Note="failed";
     }
     else{
         fieldInputter=new CCDFieldInputter(result);
         CCDField fieldG05=fieldInputter.GetFieldById("G05");
         if(fieldG05!=null) {
             etransAck.AckCode=fieldG05.valuestr;
         }
         etransAck.Etype=fieldInputter.GetEtransType();
     }
     Etranss.Insert(etransAck);
     Etranss.SetMessage(etransAck.EtransNum,result);
     etrans.AckEtransNum=etransAck.EtransNum;
     Etranss.Update(etrans);
     Etranss.SetMessage(etrans.EtransNum,strb.ToString());
     if(resultIsError){
         throw new ApplicationException(result);
     }
     if(doPrint) {
         new FormCCDPrint(etrans,result,true);//Print the form.
     }
     //Now we will process the 'result' here to extract the important data.  Basically Yes or No on the eligibility.
     //We might not do this for any other trans type besides eligibility.
     string strResponse="";//"Eligibility check on "+DateTime.Today.ToShortDateString()+"\r\n";
     //CCDField field=fieldInputter.GetFieldById("G05");//response status
     string valuestr=fieldInputter.GetValue("G05");//response status
     switch(valuestr){
         case "E":
             strResponse+="Patient is eligible.";
             break;
         case "R":
             strResponse+="Patient not eligible, or error in data.";
             break;
         case "M":
             strResponse+="Manual claimform should be submitted for employer certified plan.";
             break;
     }
     etrans=Etranss.GetEtrans(etrans.EtransNum);
     etrans.Note=strResponse;
     Etranss.Update(etrans);
     return etransAck.EtransNum;
     /*
     CCDField[] fields=fieldInputter.GetFieldsById("G08");//Error Codes
     for(int i=0;i<fields.Length;i++){
         retVal+="\r\n";
         retVal+=fields[i].valuestr;//todo: need to turn this into a readable string.
     }
     fields=fieldInputter.GetFieldsById("G32");//Display messages
     for(int i=0;i<fields.Length;i++) {
         retVal+="\r\n";
         retVal+=fields[i].valuestr;
     }
     return retVal;*/
 }
コード例 #14
0
ファイル: Etranss.cs プロジェクト: nampn/ODental
 ///<summary>Not for claim types, just other types, including Eligibility. This function gets run first.  Then, the messagetext is created and an attempt is made to send the message.  Finally, the messagetext is added to the etrans.  This is necessary because the transaction numbers must be incremented and assigned to each message before creating the message and attempting to send.  If it fails, we will need to roll back.  Provide EITHER a carrierNum OR a canadianNetworkNum.  Many transactions can be sent to a carrier or to a network.</summary>
 public static Etrans CreateCanadianOutput(long patNum,long carrierNum,long canadianNetworkNum,long clearinghouseNum,EtransType etype,long planNum,long insSubNum)
 {
     if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
         return Meth.GetObject<Etrans>(MethodBase.GetCurrentMethod(),patNum,carrierNum,canadianNetworkNum,clearinghouseNum,etype,planNum,insSubNum);
     }
     //validation of carrier vs network
     if(etype==EtransType.Eligibility_CA){
         //only carrierNum is allowed (and required)
         if(carrierNum==0){
             throw new ApplicationException("Carrier not supplied for Etranss.CreateCanadianOutput.");
         }
         if(canadianNetworkNum!=0){
             throw new ApplicationException("NetworkNum not allowed for Etranss.CreateCanadianOutput.");
         }
     }
     Etrans etrans=new Etrans();
     //etrans.DateTimeTrans handled automatically
     etrans.ClearingHouseNum=clearinghouseNum;
     etrans.Etype=etype;
     etrans.ClaimNum=0;//no claim involved
     etrans.PatNum=patNum;
     //CanadianNetworkNum?
     etrans.CarrierNum=carrierNum;
     etrans.PlanNum=planNum;
     etrans.InsSubNum=insSubNum;
     //Get next OfficeSequenceNumber-----------------------------------------------------------------------------------------
     etrans.OfficeSequenceNumber=0;
     string command="SELECT MAX(OfficeSequenceNumber) FROM etrans";
     DataTable 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.
             //get the date of the most recent max
             //This works, but it got even more complex for CarrierTransCounter, so we will just throw an exception for now.
             /*command="SELECT MAX(DateTimeTrans) FROM etrans WHERE OfficeSequenceNumber=999999";
             table=Db.GetTable(command);
             DateTime maxDateT=PIn.PDateT(table.Rows[0][0].ToString());
             //then, just get the max that's newer than that.
             command="SELECT MAX(OfficeSequenceNumber) FROM etrans WHERE DateTimeTrans > '"+POut.PDateT(maxDateT)+"'";
             table=Db.GetTable(command);
             if(table.Rows.Count>0) {
                 etrans.OfficeSequenceNumber=PIn.PInt(table.Rows[0][0].ToString());
             }*/
             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++;
     //if(etype==EtransType.Eligibility_CA){ //The counter must be incremented for all transaction types, according to the documentation for field A09 Carrier Transaction Counter.
         //find the next CarrierTransCounter------------------------------------------------------------------------------------
         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.");
             //maybe by adding a reset date to the preference table which will apply to all counters as a whole.
         }
         etrans.CarrierTransCounter++;
     //}
     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.
 }
コード例 #15
0
ファイル: CanadianOutput.cs プロジェクト: nampn/ODental
 //THIS TRANSACTION TYPE IS NOT USED BY ANY CANADIAN CARRIERS, AND IS NOT PART OF CERTIFICATION, EVEN THOUGH IT IS IN THE SPECIFICATIONS. WE NEED TO FIX BELOW COMMENTS AND MAKE THIS CODE FUNCTION MORE LIKE THE GetPaymentReconciliations() FUNCTION ABOVE.
 ///<summary>Does not exist in version 02 so only supported for version 04. Returns the request Etrans record. Usually pass in a carrier with network null.  If sending to a network, carrier will be null and we still don't see anywhere in the message format to specify network.  We expect to get clarification on this issue later. Validate provTreat as a CDANet provider before calling this function.</summary>
 public static Etrans GetSummaryReconciliation(Carrier carrier,CanadianNetwork network,Provider provTreat,DateTime reconciliationDate)
 {
     Clearinghouse clearhouse=Canadian.GetClearinghouse();
     if(clearhouse==null) {
         throw new ApplicationException("Canadian clearinghouse not found.");
     }
     string saveFolder=clearhouse.ExportPath;
     if(!Directory.Exists(saveFolder)) {
         throw new ApplicationException(saveFolder+" not found.");
     }
     StringBuilder strb=new StringBuilder();
     Etrans etrans=null;
     if(carrier!=null) {
         if((carrier.CanadianSupportedTypes&CanSupTransTypes.RequestForSummaryReconciliation_05)!=CanSupTransTypes.RequestForSummaryReconciliation_05) {
             throw new ApplicationException("The carrier does not support summary reconciliation transactions.");
         }
         etrans=Etranss.CreateCanadianOutput(0,carrier.CarrierNum,carrier.CanadianNetworkNum,
             clearhouse.ClearinghouseNum,EtransType.RequestSumm_CA,0,0);
     }
     else {//Assume network!=null
         etrans=Etranss.CreateCanadianOutput(0,0,network.CanadianNetworkNum,
             clearhouse.ClearinghouseNum,EtransType.RequestSumm_CA,0,0);
     }
     //A01 transaction prefix 12 AN
     strb.Append(Canadian.TidyAN(network.CanadianTransactionPrefix,12));
     //A02 office sequence number 6 N
     strb.Append(Canadian.TidyN(etrans.OfficeSequenceNumber,6));
     //A03 format version number 2 N
     strb.Append("04");
     //A04 transaction code 2 N
     strb.Append("05");//payment reconciliation request
     //A05 carrier id number 6 N
     if(carrier!=null) {
         strb.Append(carrier.ElectID);//already validated as 6 digit number.
     }
     else { //Assume network!=null
         strb.Append("999999");//Always 999999 when sending to a network.
     }
     //A06 software system id 3 AN
     strb.Append(Canadian.SoftwareSystemId());
     //A10 encryption method 1 N
     if(carrier!=null) {
         strb.Append(carrier.CanadianEncryptionMethod);//validated in UI
     }
     else { //Assume network!=null
         strb.Append("1");//No encryption when sending to a network.
     }
     //A07 message length N4
     strb.Append(Canadian.TidyN("63",5));
     //A09 carrier transaction counter 5 N
     strb.Append(Canadian.TidyN(etrans.CarrierTransCounter,5));
     //B01 CDA provider number 9 AN
     strb.Append(Canadian.TidyAN(provTreat.NationalProvID,9));//already validated
     //B02 (treating) provider office number 4 AN
     strb.Append(Canadian.TidyAN(provTreat.CanadianOfficeNum,4));//already validated
     //F33 Reconciliation Date 8 N
     strb.Append(reconciliationDate.ToString("yyyyMMdd"));
     //End of message construction.
     string result="";
     bool resultIsError=false;
     try {
         if(carrier!=null) {
             result=Canadian.PassToIca(strb.ToString(),clearhouse);
         }
         else { //Assume network!=null
             result=Canadian.PassToIca(strb.ToString(),clearhouse);
         }
     }
     catch(ApplicationException ex) {
         result=ex.Message;
         resultIsError=true;
         //Etranss.Delete(etrans.EtransNum);//we don't want to do this, because we want the incremented etrans.OfficeSequenceNumber to be saved
         //Attach an ack indicating failure.
     }
     //Attach an ack to the etrans
     Etrans etransAck=new Etrans();
     etransAck.PatNum=etrans.PatNum;
     etransAck.PlanNum=etrans.PlanNum;
     etransAck.InsSubNum=etrans.InsSubNum;
     etransAck.CarrierNum=etrans.CarrierNum;
     etransAck.DateTimeTrans=DateTime.Now;
     CCDFieldInputter fieldInputter=null;
     if(resultIsError) {
         etransAck.Etype=EtransType.AckError;
         etrans.Note="failed";
     }
     else {
         fieldInputter=new CCDFieldInputter(result);
         CCDField fieldG05=fieldInputter.GetFieldById("G05");
         if(fieldG05!=null) {
             etransAck.AckCode=fieldG05.valuestr;
         }
         etransAck.Etype=fieldInputter.GetEtransType();
     }
     Etranss.Insert(etransAck);
     Etranss.SetMessage(etransAck.EtransNum,result);
     etrans.AckEtransNum=etransAck.EtransNum;
     Etranss.Update(etrans);
     Etranss.SetMessage(etrans.EtransNum,strb.ToString());
     if(resultIsError) {
         throw new ApplicationException(result);
     }
     new FormCCDPrint(etrans,result,true);
     return etrans;
 }
コード例 #16
0
ファイル: CanadianOutput.cs プロジェクト: nampn/ODental
 ///<summary></summary>
 public static long SendClaimReversal(Claim claim,InsPlan plan,InsSub insSub)
 {
     StringBuilder strb=new StringBuilder();
     Clearinghouse clearhouse=Canadian.GetClearinghouse();
     if(clearhouse==null) {
         throw new ApplicationException(Lan.g("CanadianOutput","Canadian clearinghouse not found."));
     }
     string saveFolder=clearhouse.ExportPath;
     if(!Directory.Exists(saveFolder)) {
         throw new ApplicationException(saveFolder+" not found.");
     }
     Carrier carrier=Carriers.GetCarrier(plan.CarrierNum);
     if((carrier.CanadianSupportedTypes&CanSupTransTypes.ClaimReversal_02)!=CanSupTransTypes.ClaimReversal_02) {
         throw new ApplicationException(Lan.g("CanadianOutput","The carrier does not support reversal transactions."));
     }
     if(carrier.CanadianNetworkNum==0) {
         throw new ApplicationException("Carrier network not set.");
     }
     CanadianNetwork network=CanadianNetworks.GetNetwork(carrier.CanadianNetworkNum);
     Etrans etrans=Etranss.CreateCanadianOutput(claim.PatNum,carrier.CarrierNum,carrier.CanadianNetworkNum,
         clearhouse.ClearinghouseNum,EtransType.ClaimReversal_CA,plan.PlanNum,insSub.InsSubNum);
     etrans.ClaimNum=claim.ClaimNum;//We don't normally use a claim number with Etranss.CreateCanadianOutput(), but here we need the claim number so that we can show the claim reversal in the claim history.
     Etranss.Update(etrans);
     Patient patient=Patients.GetPat(claim.PatNum);
     Provider prov=Providers.GetProv(claim.ProvTreat);
     if(!prov.IsCDAnet) {
         throw new ApplicationException(Lan.g("CanadianOutput","Treating provider is not setup to use CDANet."));
     }
     Provider billProv=ProviderC.ListLong[Providers.GetIndexLong(claim.ProvBill)];
     if(!billProv.IsCDAnet) {
         throw new ApplicationException(Lan.g("CanadianOutput","Billing provider is not setup to use CDANet."));
     }
     InsPlan insPlan=InsPlans.GetPlan(claim.PlanNum,new List<InsPlan>());
     Patient subscriber=Patients.GetPat(insSub.Subscriber);
     //create message----------------------------------------------------------------------------------------------
     //A01 transaction prefix 12 AN
     strb.Append(Canadian.TidyAN(network.CanadianTransactionPrefix,12));
     //A02 office sequence number 6 N
     //We are required to use the same office sequence number as the original claim.
     etrans.OfficeSequenceNumber=0;//Clear the randomly generated office sequence number.
     List<Etrans> claimTransactions=Etranss.GetAllForOneClaim(claim.ClaimNum);
     DateTime originalEtransDateTime=DateTime.MinValue;//So we can get the latest matching transaction.
     for(int i=0;i<claimTransactions.Count;i++) {
         if(claimTransactions[i].Etype==EtransType.Claim_CA || claimTransactions[i].Etype==EtransType.ClaimCOB_CA) {
             Etrans ack=Etranss.GetEtrans(claimTransactions[i].AckEtransNum);
             if(ack==null) {//For those claims sent that didn't receive a response (i.e. when there is an exception while sending a claim).
                 continue;
             }
             string messageText=EtransMessageTexts.GetMessageText(ack.EtransMessageTextNum);
             CCDFieldInputter messageData=new CCDFieldInputter(messageText);
             CCDField transRefNum=messageData.GetFieldById("G01");
             if(transRefNum!=null && transRefNum.valuestr==claim.CanadaTransRefNum && claimTransactions[i].DateTimeTrans>originalEtransDateTime) {
                 etrans.OfficeSequenceNumber=PIn.Int(messageData.GetFieldById("A02").valuestr);
                 originalEtransDateTime=claimTransactions[i].DateTimeTrans;
             }
         }
     }
     DateTime serverDate=MiscData.GetNowDateTime().Date;
     if(originalEtransDateTime.Date!=serverDate) {
         throw new ApplicationException(Lan.g("CanadianOutput","Claims can only be reversed on the day that they were sent. The claim can only be manually reversed."));
     }
     strb.Append(Canadian.TidyN(etrans.OfficeSequenceNumber,6));
     //A03 format version number 2 N
     strb.Append(carrier.CDAnetVersion);//eg. "04", validated in UI
     //A04 transaction code 2 N
     strb.Append("02");//Same for both versions 02 and 04.
     //A05 carrier id number 6 N
     strb.Append(carrier.ElectID);//already validated as 6 digit number.
     //A06 software system id 3 AN
     strb.Append(Canadian.SoftwareSystemId());
     if(carrier.CDAnetVersion!="02") { //version 04
         //A10 encryption method 1 N
         strb.Append(carrier.CanadianEncryptionMethod);//validated in UI
     }
     if(carrier.CDAnetVersion=="02") {
         //A07 message length N4
         strb.Append(Canadian.TidyN("133",4));
     }
     else { //version 04
         //A07 message length N 5
         strb.Append(Canadian.TidyN("164",5));
     }
     if(carrier.CDAnetVersion!="02") { //version 04
         //A09 carrier transaction counter 5 N
     #if DEBUG
         strb.Append("11111");
     #else
         strb.Append(Canadian.TidyN(etrans.CarrierTransCounter,5));
     #endif
     }
     //B01 CDA provider number 9 AN
     strb.Append(Canadian.TidyAN(prov.NationalProvID,9));//already validated
     //B02 provider office number 4 AN
     strb.Append(Canadian.TidyAN(prov.CanadianOfficeNum,4));//already validated
     if(carrier.CDAnetVersion!="02") { //version 04
         //B03 billing provider number 9 AN
         //might need to account for possible 5 digit prov id assigned by carrier
         strb.Append(Canadian.TidyAN(billProv.NationalProvID,9));//already validated
         //B04 billing provider office number 4 AN
         strb.Append(Canadian.TidyAN(billProv.CanadianOfficeNum,4));//already validated
     }
     if(carrier.CDAnetVersion=="02") {
         //C01 primary policy/plan number 8 AN
         //only validated to ensure that it's not blank and is less than 8. Also that no spaces.
         strb.Append(Canadian.TidyAN(insPlan.GroupNum,8));
     }
     else { //version 04
         //C01 primary policy/plan number 12 AN
         //only validated to ensure that it's not blank and is less than 12. Also that no spaces.
         strb.Append(Canadian.TidyAN(insPlan.GroupNum,12));
     }
     //C11 primary division/section number 10 AN
     strb.Append(Canadian.TidyAN(insPlan.DivisionNo,10));
     if(carrier.CDAnetVersion=="02") {
         //C02 subscriber id number 11 AN
         strb.Append(Canadian.TidyAN(insSub.SubscriberID.Replace("-",""),11));//validated
     }
     else { //version 04
         //C02 subscriber id number 12 AN
         strb.Append(Canadian.TidyAN(insSub.SubscriberID.Replace("-",""),12));//validated
     }
     //C03 relationship code 1 N
     //User interface does not only show Canadian options, but all options are handled.
     strb.Append(Canadian.GetRelationshipCode(claim.PatRelat));
     if(carrier.CDAnetVersion=="02") {
         //D02 subscriber last name 25 A
         strb.Append(Canadian.TidyA(subscriber.LName,25));//validated
     }
     else { //version 04
         //D02 subscriber last name 25 AE
         strb.Append(Canadian.TidyAE(subscriber.LName,25,true));//validated
     }
     if(carrier.CDAnetVersion=="02") {
         //D03 subscriber first name 15 A
         strb.Append(Canadian.TidyA(subscriber.FName,15));//validated
     }
     else { //version 04
         //D03 subscriber first name 15 AE
         strb.Append(Canadian.TidyAE(subscriber.FName,15,true));//validated
     }
     if(carrier.CDAnetVersion=="02") {
         //D04 subscriber middle initial 1 A
         strb.Append(Canadian.TidyA(subscriber.MiddleI,1));
     }
     else { //version 04
         //D04 subscriber middle initial 1 AE
         strb.Append(Canadian.TidyAE(subscriber.MiddleI,1));
     }
     if(carrier.CDAnetVersion!="02") { //version 04
         //For Future Use
         strb.Append("000000");
     }
     //G01 transaction reference number of original claim AN 14
     strb.Append(Canadian.TidyAN(claim.CanadaTransRefNum,14));
     string result="";
     bool resultIsError=false;
     try {
       result=Canadian.PassToIca(strb.ToString(),clearhouse);
     }
     catch(ApplicationException ex) {
       result=ex.Message;
       resultIsError=true;
       //Etranss.Delete(etrans.EtransNum);//we don't want to do this, because we want the incremented etrans.OfficeSequenceNumber to be saved
       //Attach an ack indicating failure.
     }
     //Attach an ack to the etrans
     Etrans etransAck=new Etrans();
     etransAck.PatNum=etrans.PatNum;
     etransAck.PlanNum=etrans.PlanNum;
     etransAck.InsSubNum=etrans.InsSubNum;
     etransAck.CarrierNum=etrans.CarrierNum;
     etransAck.DateTimeTrans=DateTime.Now;
     if(resultIsError) {
         etransAck.AckCode="R";//To allow the user to try and reverse the claim again.
       etransAck.Etype=EtransType.AckError;
       etrans.Note="failed";
     }
     else {
         try {
             CCDFieldInputter fieldInputter=new CCDFieldInputter(result);
             CCDField fieldG05=fieldInputter.GetFieldById("G05");
             if(fieldG05!=null) {
                 etransAck.AckCode=fieldG05.valuestr;
             }
             etransAck.Etype=fieldInputter.GetEtransType();
         }
         catch {
             etransAck.AckCode="R";//To allow the user to try and reverse the claim again.
             etransAck.Etype=EtransType.AckError;
             etrans.Note="Could not parse response from ITRANS.";
         }
     }
     Etranss.Insert(etransAck);
     Etranss.SetMessage(etransAck.EtransNum,result);
     etrans.AckEtransNum=etransAck.EtransNum;
     Etranss.Update(etrans);
     Etranss.SetMessage(etrans.EtransNum,strb.ToString());
     if(resultIsError) {
       throw new ApplicationException(result);
     }
     new FormCCDPrint(etrans,result,true);//Print the response.
     if(etrans.AckCode=="R") {
         throw new ApplicationException(Lan.g("CanadianOutput","Reversal was rejected by clearinghouse. The claim must be reversed manually."));
     }
     return etransAck.EtransNum;
 }
コード例 #17
0
ファイル: Etranss.cs プロジェクト: nampn/ODental
        ///<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);
            }
        }
コード例 #18
0
ファイル: Etranss.cs プロジェクト: ChemBrain/OpenDental
		///<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);
			}
		}
コード例 #19
0
ファイル: x270Controller.cs プロジェクト: mnisl/OD
		///<summary>The insplan that's passed in need not be properly updated to the database first.</summary>
		public static void RequestBenefits(Clearinghouse clearhouse,InsPlan plan,long patNum,Carrier carrier,List<Benefit> benList,long patPlanNum,InsSub insSub) {
			Patient pat=Patients.GetPat(patNum);
			Patient subsc=Patients.GetPat(insSub.Subscriber);
			Clinic clinic=Clinics.GetClinic(pat.ClinicNum);
			Provider billProv=Providers.GetProv(Providers.GetBillingProvNum(pat.PriProv,pat.ClinicNum));
			//validation.  Throw exception if missing info----------------------------------------
			string validationResult=X270.Validate(clearhouse,carrier,billProv,clinic,plan,subsc,insSub);
			if(validationResult != "") {
				throw new Exception(Lan.g("FormInsPlan","Please fix the following errors first:")+"\r\n"+validationResult);
			}
			//create a 270 message---------------------------------------------------------------
			string x12message=X270.GenerateMessageText(clearhouse,carrier,billProv,clinic,plan,subsc,insSub);
			EtransMessageText etransMessageText=new EtransMessageText();
			etransMessageText.MessageText=x12message;
			EtransMessageTexts.Insert(etransMessageText);
			//attach it to an etrans-------------------------------------------------------------
			Etrans etrans=new Etrans();
			etrans.DateTimeTrans=DateTime.Now;
			etrans.ClearingHouseNum=clearhouse.ClearinghouseNum;
			etrans.Etype=EtransType.BenefitInquiry270;
			etrans.PlanNum=plan.PlanNum;
			etrans.InsSubNum=insSub.InsSubNum;
			etrans.EtransMessageTextNum=etransMessageText.EtransMessageTextNum;
			Etranss.Insert(etrans);
			//send the 270----------------------------------------------------------------------
			string x12response="";
			//a connection error here needs to bubble up
			try {
				if(clearhouse.CommBridge==EclaimsCommBridge.ClaimConnect) {
					x12response=ClaimConnect.Benefits270(clearhouse,x12message);
				}
				if(clearhouse.CommBridge==EclaimsCommBridge.EDS) {
					x12response=EDS.Benefits270(clearhouse,x12message);
				}
			}
			catch(Exception ex) {
				EtransMessageTexts.Delete(etrans.EtransMessageTextNum);
				Etranss.Delete(etrans.EtransNum);
				throw new ApplicationException(Lan.g("FormInsPlan","Connection Error:")+"\r\n"+ex.GetType().Name+"\r\n"+ex.Message);
			}
			//start to process the 271----------------------------------------------------------
			X271 x271=null;
			if(X12object.IsX12(x12response)) {
				X12object x12obj=new X12object(x12response);
				if(x12obj.Is271()) {
					x271=new X271(x12response);
				}
			}
			else {//not a 997, 999, 277 or 271
				EtransMessageTexts.Delete(etrans.EtransMessageTextNum);
				Etranss.Delete(etrans.EtransNum);
				throw new ApplicationException(Lan.g("FormInsPlan","Error:")+"\r\n"+x12response);
			}
			/*
			//In realtime mode, X12 limits the request to one patient.
			//We will always use the subscriber.
			//So all EB segments are for the subscriber.
			List<EB271> listEB=new List<EB271>();
			EB271 eb;
			if(x271 != null) {
				for(int i=0;i<x271.Segments.Count;i++) {
					if(x271.Segments[i].SegmentID != "EB") {
						continue;
					}
					eb=new EB271(x271.Segments[i]);
					listEB.Add(eb);
				}
			}*/
			//create an etrans for the 271------------------------------------------------------
			etransMessageText=new EtransMessageText();
			etransMessageText.MessageText=x12response;
			EtransMessageTexts.Insert(etransMessageText);
			Etrans etrans271=new Etrans();
			etrans271.DateTimeTrans=DateTime.Now;
			etrans271.ClearingHouseNum=clearhouse.ClearinghouseNum;
			etrans271.Etype=EtransType.TextReport;
			if(X12object.IsX12(x12response)) {//this shouldn't need to be tested because it was tested above.
				if(x271==null){
					X12object Xobj=new X12object(x12response);
					if(Xobj.Is997()) {
						etrans271.Etype=EtransType.Acknowledge_997;
					}
					else if(Xobj.Is999()) {
						etrans271.Etype=EtransType.Acknowledge_999;
					}
					else if(X277.Is277(Xobj)) {
						etrans271.Etype=EtransType.StatusNotify_277;
					}
					else if(X835.Is835(Xobj)) {
						etrans271.Etype=EtransType.ERA_835;
					}
				}
				else{
					etrans271.Etype=EtransType.BenefitResponse271;
				}
			}
			etrans271.PlanNum=plan.PlanNum;
			etrans271.InsSubNum=insSub.InsSubNum;
			etrans271.EtransMessageTextNum=etransMessageText.EtransMessageTextNum;
			Etranss.Insert(etrans271);
			etrans.AckEtransNum=etrans271.EtransNum;
			if(etrans271.Etype==EtransType.Acknowledge_997) {
				X997 x997=new X997(x12response);
				string error997=x997.GetHumanReadable();
				etrans.Note="Error: "+error997;//"Malformed document sent.  997 error returned.";
				Etranss.Update(etrans);
				MessageBox.Show(etrans.Note);
				//CodeBase.MsgBoxCopyPaste msgbox=new CodeBase.MsgBoxCopyPaste(etrans.Note);
				//msgbox.ShowDialog();
				//don't show the 270 interface.
				return;
			}
			else if(etrans271.Etype==EtransType.Acknowledge_999) {
				X999 x999=new X999(x12response);
				string error999=x999.GetHumanReadable();
				etrans.Note="Error: "+error999;//"Malformed document sent.  999 error returned.";
				Etranss.Update(etrans);
				MessageBox.Show(etrans.Note);
				//CodeBase.MsgBoxCopyPaste msgbox=new CodeBase.MsgBoxCopyPaste(etrans.Note);
				//msgbox.ShowDialog();
				//don't show the 270 interface.
				return;
			}
			else if(etrans271.Etype==EtransType.StatusNotify_277) { 
				X277 x277=new X277(x12response);
				string error277=x277.GetHumanReadable();
				etrans.Note="Error: "+error277;//"Malformed document sent.  277 error returned.";
				Etranss.Update(etrans);
				MessageBox.Show(etrans.Note);
				//CodeBase.MsgBoxCopyPaste msgbox=new CodeBase.MsgBoxCopyPaste(etrans.Note);
				//msgbox.ShowDialog();
				//don't show the 277 interface.
				return;
			}
			else if(etrans271.Etype==EtransType.ERA_835) {
				X835 x835=new X835(x12response,"");
				string error835=x835.GetHumanReadable();
				etrans.Note="Error: "+error835;//"Malformed document sent.  835 error returned.";
				Etranss.Update(etrans);
				MessageBox.Show(etrans.Note);
				//CodeBase.MsgBoxCopyPaste msgbox=new CodeBase.MsgBoxCopyPaste(etrans.Note);
				//msgbox.ShowDialog();
				//don't show the 835 interface.
				return;
			}
			else { //271
				string processingerror=x271.GetProcessingError();
				if(processingerror != "") {
					etrans.Note=processingerror;
					Etranss.Update(etrans);
					MessageBox.Show(etrans.Note);
					//CodeBase.MsgBoxCopyPaste msgbox=new CodeBase.MsgBoxCopyPaste(etrans.Note);
					//msgbox.ShowDialog();
					//don't show the 270 interface.
					return;
				}
				else {
					etrans.Note="Normal 271 response.";//change this later to be explanatory of content.
				}
			}
			Etranss.Update(etrans);
			//show the user a list of benefits to pick from for import--------------------------
			FormEtrans270Edit formE=new FormEtrans270Edit(patPlanNum,plan.PlanNum,insSub.InsSubNum);
			formE.EtransCur=etrans;
			formE.IsInitialResponse=true;
			formE.benList=benList;
			formE.ShowDialog();
		}
コード例 #20
0
ファイル: ItransNCpl.cs プロジェクト: kjb7749/testImport
        ///<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.
        }
コード例 #21
0
ファイル: Etranss.cs プロジェクト: steev90/opendental
        ///<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.
        }
コード例 #22
0
ファイル: Canadian.cs プロジェクト: mnisl/OD
		///<summary>Called directly instead of from Eclaims.SendBatches.  Includes one claim.  Sets claim status internally if successfully sent.  Returns the EtransNum of the ack.  Includes various user interaction such as displaying of messages, printing, triggering of COB claims, etc.  For a normal claim, primaryEOB will be blank.  But if this is a COB(type7), then we need to embed the primary EOB by passing it in. The queueItem.ClearinghouseNum must refer to a valid Canadian clearinghouse.</summary>
		public static long SendClaim(ClaimSendQueueItem queueItem,bool doPrint){
			Clearinghouse clearhouse=Clearinghouses.GetClearinghouse(queueItem.ClearinghouseNum);
//Warning: this path is not handled properly if trailing slash is missing:
			string saveFolder=clearhouse.ExportPath;
			if(!Directory.Exists(saveFolder)) {
				throw new ApplicationException(saveFolder+" not found.");
			}
			Etrans etrans;
			Claim claim;
			Clinic clinic;
			Provider billProv;
			Provider treatProv;
			InsPlan insPlan;
			InsSub insSub;
			Carrier carrier;
			InsPlan insPlan2=null;
			InsSub insSub2=null;
			Carrier carrier2=null;
			List <PatPlan> patPlansForPatient;
			Patient patient;
			Patient subscriber;
			List<ClaimProc> claimProcList;//all claimProcs for a patient.
			List<ClaimProc> claimProcsClaim;
			List<Procedure> procListAll;
			List<Procedure> extracted;
			List<Procedure> procListLabForOne;//Lab fees for one procedure
			Patient subscriber2=null;
			Procedure proc;
			ProcedureCode procCode;
			StringBuilder strb;
			string primaryEOBResponse="";
			string primaryClaimRequestMessage="";
			claim=Claims.GetClaim(queueItem.ClaimNum);
			claimProcList=ClaimProcs.Refresh(claim.PatNum);
			claimProcsClaim=ClaimProcs.GetForSendClaim(claimProcList,claim.ClaimNum);
			long planNum=claim.PlanNum;
			long insSubNum=claim.InsSubNum;
			Relat patRelat=claim.PatRelat;
			long planNum2=claim.PlanNum2;
			long insSubNum2=claim.InsSubNum2;
			Relat patRelat2=claim.PatRelat2;
			if(claim.ClaimType=="PreAuth") {
				etrans=Etranss.SetClaimSentOrPrinted(queueItem.ClaimNum,queueItem.PatNum,clearhouse.ClearinghouseNum,EtransType.Predeterm_CA,0);
			}
			else if(claim.ClaimType=="S") {//Secondary
				//We first need to verify that the claimprocs on the secondary/cob claim are the same as the claimprocs on the primary claim.
				etrans=Etranss.SetClaimSentOrPrinted(queueItem.ClaimNum,queueItem.PatNum,clearhouse.ClearinghouseNum,EtransType.ClaimCOB_CA,0);
				long claimNumPrimary=0;
				for(int i=0;i<claimProcsClaim.Count;i++) {
					List<ClaimProc> claimProcsForProc=ClaimProcs.GetForProc(claimProcList,claimProcsClaim[i].ProcNum);
					bool matchingPrimaryProc=false;
					for(int j=0;j<claimProcsForProc.Count;j++) {
						if(claimProcsForProc[j].ClaimNum!=0 && claimProcsForProc[j].ClaimNum!=claim.ClaimNum && (claimNumPrimary==0 || claimNumPrimary==claimProcsForProc[j].ClaimNum)) {
							claimNumPrimary=claimProcsForProc[j].ClaimNum;
							matchingPrimaryProc=true;
							break;
						}
					}
					if(!matchingPrimaryProc) {
						throw new ApplicationException(Lan.g("Canadian","The procedures attached to this COB claim must be the same as the procedures attached to the primary claim."));
					}
				}
				if(ClaimProcs.GetForSendClaim(claimProcList,claimNumPrimary).Count!=claimProcsClaim.Count) {
					throw new ApplicationException(Lan.g("Canadian","The procedures attached to this COB claim must be the same as the procedures attached to the primary claim."));
				}
				//Now ensure that the primary claim recieved an EOB response, or else we cannot send a COB.
				List <Etrans> etransPrimary=Etranss.GetHistoryOneClaim(claimNumPrimary);
				for(int i=0;i<etransPrimary.Count;i++) {
					primaryClaimRequestMessage=EtransMessageTexts.GetMessageText(etransPrimary[i].EtransMessageTextNum);
					Etrans etransPrimaryAck=Etranss.GetEtrans(etransPrimary[i].AckEtransNum);
					if(etransPrimaryAck.AckCode.ToUpper()=="R") {
						continue;
					}
					if(etransPrimaryAck!=null) {
						primaryEOBResponse=EtransMessageTexts.GetMessageText(etransPrimaryAck.EtransMessageTextNum);
					}
					break;
				}
				if(primaryEOBResponse=="") {
					throw new ApplicationException(Lan.g("Canadian","Cannot send secondary claim electronically until primary EOB has been received electronically."));
				}
				else if(primaryEOBResponse.Length<22) {
					throw new ApplicationException(Lan.g("Canadian","Cannot send secondary claim electronically, because primary claim electronic response is malformed. Try sending the primary claim again."));
				}
				else {//primaryEOBResponse.Length>=22
					string messageVersion=primaryEOBResponse.Substring(18,2);//Field A03 always exists on all messages and is always in the same location.
					string messageType=primaryEOBResponse.Substring(20,2);//Field A04 always exists on all messages and is always in the same location.
					if(messageVersion!="04") {
						throw new ApplicationException(Lan.g("Canadian","Cannot send secondary claim electronically, because primary claim electronic response is in an older format. The secondary claim must be printed instead."));
					}
					if(messageType!="21") {//message type 21 is EOB
						throw new ApplicationException(Lan.g("Canadian","Cannot send secondary claim electronically until primary EOB has been received electronically. The existing primary claim electronic response is not an EOB."));
					}
				}
				Claim claimPrimary=Claims.GetClaim(claimNumPrimary);
				planNum=claimPrimary.PlanNum;
				insSubNum=claimPrimary.InsSubNum;
				patRelat=claimPrimary.PatRelat;
				planNum2=claimPrimary.PlanNum2;
				insSubNum2=claimPrimary.InsSubNum2;
				patRelat2=claimPrimary.PatRelat2;
			}
			else { //primary claim
				etrans=Etranss.SetClaimSentOrPrinted(queueItem.ClaimNum,queueItem.PatNum,clearhouse.ClearinghouseNum,EtransType.Claim_CA,0);
			}
			claim=Claims.GetClaim(claim.ClaimNum);//Refresh the claim since the status might have changed above.
			clinic=Clinics.GetClinic(claim.ClinicNum);
			billProv=ProviderC.ListLong[Providers.GetIndexLong(claim.ProvBill)];
			treatProv=ProviderC.ListLong[Providers.GetIndexLong(claim.ProvTreat)];
			insPlan=InsPlans.GetPlan(planNum,new List <InsPlan> ());
			insSub=InsSubs.GetSub(insSubNum,new List<InsSub>());
			if(planNum2>0) {
				insPlan2=InsPlans.GetPlan(planNum2,new List<InsPlan>());
				insSub2=InsSubs.GetSub(insSubNum2,new List<InsSub>());
				carrier2=Carriers.GetCarrier(insPlan2.CarrierNum);
				subscriber2=Patients.GetPat(insSub2.Subscriber);
			}
			if(claim.ClaimType=="S") {
				carrier=Carriers.GetCarrier(insPlan2.CarrierNum);
			}
			else {
				carrier=Carriers.GetCarrier(insPlan.CarrierNum);
			}
			CanadianNetwork network=CanadianNetworks.GetNetwork(carrier.CanadianNetworkNum);
			patPlansForPatient=PatPlans.Refresh(claim.PatNum);
			patient=Patients.GetPat(claim.PatNum);
			subscriber=Patients.GetPat(insSub.Subscriber);
			procListAll=Procedures.Refresh(claim.PatNum);
			extracted=Procedures.GetCanadianExtractedTeeth(procListAll);
			strb=new StringBuilder();
			//A01 transaction prefix 12 AN
			strb.Append(TidyAN(network.CanadianTransactionPrefix,12));
			//A02 office sequence number 6 N
			strb.Append(TidyN(etrans.OfficeSequenceNumber,6));
			//A03 format version number 2 N
			if(carrier.CDAnetVersion=="") {
				strb.Append("04");
			}
			else {
				strb.Append(carrier.CDAnetVersion);
			}
			//A04 transaction code 2 N
			if(claim.ClaimType=="PreAuth") {
				strb.Append("03");//Predetermination
			}
			else {
				if(claim.ClaimType=="S") {
					strb.Append("07");//cob
				}
				else {
					strb.Append("01");//claim
				}
			}
			//A05 carrier id number 6 N
			strb.Append(carrier.ElectID);//already validated as 6 digit number.
			//A06 software system id 3 AN
			strb.Append(SoftwareSystemId());
			if(carrier.CDAnetVersion!="02") { //version 04
				//A10 encryption method 1 N
				strb.Append(carrier.CanadianEncryptionMethod);//validated in UI
			}
			//A07 message length. 5 N in version 04, 4 N in version 02
			//We simply create a place holder here. We come back at the end of message construction and record the actual final message length.
			if(carrier.CDAnetVersion=="02") {
				strb.Append("0000");
			}
			else { //version 04
				strb.Append("00000");
			}
			if(carrier.CDAnetVersion=="02") {
				//A08 email flag 1 N
				if(claim.CanadianMaterialsForwarded=="") {
					strb.Append("0"); //no additional information
				}
				else if(claim.CanadianMaterialsForwarded.Contains("E")) {
					strb.Append("1"); //E-Mail to follow.
				}
				else {
					strb.Append("2"); //Letter to follow
				}
			}
			else { //version 04
				//A08 materials forwarded 1 AN
				strb.Append(GetMaterialsForwarded(claim.CanadianMaterialsForwarded));
			}
			if(carrier.CDAnetVersion!="02") { //version 04
				//A09 carrier transaction counter 5 N
#if DEBUG
				strb.Append("00001");
#else				
				strb.Append(TidyN(etrans.CarrierTransCounter,5));
#endif
			}
			//B01 CDA provider number 9 AN
			strb.Append(TidyAN(treatProv.NationalProvID,9));//already validated
			//B02 (treating) provider office number 4 AN
			strb.Append(TidyAN(treatProv.CanadianOfficeNum,4));//already validated	
			if(carrier.CDAnetVersion!="02") { //version 04
				//B03 billing provider number 9 AN
				//might need to account for possible 5 digit prov id assigned by carrier
				strb.Append(TidyAN(billProv.NationalProvID,9));//already validated
				//B04 billing provider office number 4 AN
				strb.Append(TidyAN(billProv.CanadianOfficeNum,4));//already validated	
				//B05 referring provider 10 AN
				strb.Append(TidyAN(claim.CanadianReferralProviderNum,10));
				//B06 referral reason 2 N
				strb.Append(TidyN(claim.CanadianReferralReason,2));
			}
			if(carrier.CDAnetVersion=="02") {
				//C01 primary policy/plan number 8 AN
				//only validated to ensure that it's not blank and is less than 8. Also that no spaces.
				strb.Append(TidyAN(insPlan.GroupNum,8));
			}
			else { //version 04
				//C01 primary policy/plan number 12 AN
				//only validated to ensure that it's not blank and is less than 12. Also that no spaces.
				strb.Append(TidyAN(insPlan.GroupNum,12));
			}
			//C11 primary division/section number 10 AN
			strb.Append(TidyAN(insPlan.DivisionNo,10));
			if(carrier.CDAnetVersion=="02") {
				//C02 subscriber id number 11 AN
				strb.Append(TidyAN(insSub.SubscriberID.Replace("-",""),11));//validated
			}
			else { //version 04
				//C02 subscriber id number 12 AN
				strb.Append(TidyAN(insSub.SubscriberID.Replace("-",""),12));//validated
			}
			if(carrier.CDAnetVersion!="02") { //version 04
				//C17 primary dependant code 2 N
				string patID="";
				for(int p=0;p<patPlansForPatient.Count;p++) {
					if(patPlansForPatient[p].InsSubNum==insSubNum) {
						patID=patPlansForPatient[p].PatID;
					}
				}
				strb.Append(TidyN(patID,2));
			}
			//C03 relationship code 1 N
			//User interface does not only show Canadian options, but all options are handled.
			strb.Append(GetRelationshipCode(patRelat));
			//C04 patient's sex 1 A
			//validated to not include "unknown"
			if(patient.Gender==PatientGender.Male){
				strb.Append("M");
			}
			else{
				strb.Append("F");
			}
			//C05 patient birthday 8 N
			strb.Append(patient.Birthdate.ToString("yyyyMMdd"));//validated
			if(carrier.CDAnetVersion=="02") {
				//C06 patient last name 25 A
				strb.Append(TidyA(patient.LName,25));//validated
			}
			else { //version 04
				//C06 patient last name 25 AE
				strb.Append(TidyAE(patient.LName,25,true));//validated
			}
			if(carrier.CDAnetVersion=="02") {
				//C07 patient first name 15 A
				strb.Append(TidyA(patient.FName,15));//validated
			}
			else { //version 04
				//C07 patient first name 15 AE
				strb.Append(TidyAE(patient.FName,15,true));//validated
			}
			if(carrier.CDAnetVersion=="02") {
				//C08 patient middle initial 1 A
				strb.Append(TidyA(patient.MiddleI,1));
			}
			else { //version 04
				//C08 patient middle initial 1 AE
				strb.Append(TidyAE(patient.MiddleI,1));
			}
			if(carrier.CDAnetVersion=="02") {
				//C09 eligibility exception code 1 N
				string exceptionCode=TidyN(patient.CanadianEligibilityCode,1);//Validated.
				if(exceptionCode=="4") {
					exceptionCode="0";//Code 4 in version 04 means "code not applicable", but in version 02, value 0 means "code not applicable".
				}
				strb.Append(exceptionCode);//validated
			}
			else { //version 04
				//C09 eligibility exception code 1 N
				strb.Append(TidyN((patient.CanadianEligibilityCode==0)?4:patient.CanadianEligibilityCode,1));//Validated. Use "code not applicable" when no value has been specified by the user.
			}
			if(carrier.CDAnetVersion=="02") {
				//C10 name of school 25 A
				//validated if patient 18yrs or older and full-time student (or disabled student)
				strb.Append(TidyA(patient.SchoolName,25));
			}
			else { //version 04
				//C10 name of school 25 AEN
				//validated if patient 18yrs or older and full-time student (or disabled student)
				strb.Append(TidyAEN(patient.SchoolName,25));
			}
			bool C19PlanRecordPresent=(insPlan.CanadianPlanFlag=="A" || insPlan.CanadianPlanFlag=="N" || insPlan.CanadianPlanFlag=="V");
			if(carrier.CDAnetVersion!="02") { //version 04
				//C12 plan flag 1 A
				strb.Append(Canadian.GetPlanFlag(insPlan.CanadianPlanFlag));
				//C18 plan record count 1 N
				if(C19PlanRecordPresent) {
					strb.Append("1");
				}
				else {
					strb.Append("0");
				}
			}
			CCDFieldInputter primaryClaimData=null;
			if(claim.ClaimType=="S") {
				primaryClaimData=new CCDFieldInputter(primaryClaimRequestMessage);
			}
			//D01 subscriber birthday 8 N
			strb.Append(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D01").valuestr:subscriber.Birthdate.ToString("yyyyMMdd"));//validated
			if(carrier.CDAnetVersion=="02") {
				//D02 subscriber last name 25 A
				strb.Append(TidyA(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D02").valuestr:subscriber.LName,25));//validated
			}
			else { //version 04
				//D02 subscriber last name 25 AE
				strb.Append(TidyAE(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D02").valuestr:subscriber.LName,25,true));//validated
			}
			if(carrier.CDAnetVersion=="02") {
				//D03 subscriber first name 15 A
				strb.Append(TidyA(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D03").valuestr:subscriber.FName,15));//validated
			}
			else { //version 04
				//D03 subscriber first name 15 AE
				strb.Append(TidyAE(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D03").valuestr:subscriber.FName,15,true));//validated
			}
			if(carrier.CDAnetVersion=="02") {
				//D04 subscriber middle initial 1 A
				strb.Append(TidyA(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D04").valuestr:subscriber.MiddleI,1));
			}
			else { //version 04
				//D04 subscriber middle initial 1 AE
				strb.Append(TidyAE(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D04").valuestr:subscriber.MiddleI,1));
			}
			if(carrier.CDAnetVersion=="02") {
				//D05 subscriber address line one 30 AN
				strb.Append(TidyAN(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D05").valuestr:subscriber.Address,30,true));//validated
			}
			else { //version 04
				//D05 subscriber address line one 30 AEN
				strb.Append(TidyAEN(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D05").valuestr:subscriber.Address,30,true));//validated
			}
			if(carrier.CDAnetVersion=="02") {
				//D06 subscriber address line two 30 AN
				strb.Append(TidyAN(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D06").valuestr:subscriber.Address2,30,true));
			}
			else { //version 04
				//D06 subscriber address line two 30 AEN
				strb.Append(TidyAEN(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D06").valuestr:subscriber.Address2,30,true));
			}
			if(carrier.CDAnetVersion=="02") {
				//D07 subscriber city 20 A
				strb.Append(TidyA(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D07").valuestr:subscriber.City,20));//validated
			}
			else { //version 04
				//D07 subscriber city 20 AEN
				strb.Append(TidyAEN(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D07").valuestr:subscriber.City,20,true));//validated
			}
			//D08 subscriber province/state 2 A
			strb.Append(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D08").valuestr:subscriber.State);//very throroughly validated previously
			if(carrier.CDAnetVersion=="02") {
				//D09 subscriber postal/zip code 6 AN
				strb.Append(TidyAN(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D09").valuestr:subscriber.Zip.Replace("-","").Replace(" ",""),6));//validated.
			}
			else { //version 04
				//D09 subscriber postal/zip code 9 AN
				strb.Append(TidyAN(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D09").valuestr:subscriber.Zip.Replace("-","").Replace(" ",""),9));//validated.
			}
			//D10 language of insured 1 A
			strb.Append(claim.ClaimType=="S"?primaryClaimData.GetFieldById("D10").valuestr:(subscriber.Language=="fr"?"F":"E"));
			bool orthoRecordFlag=false;
			if(carrier.CDAnetVersion!="02") { //version 04
				//D11 card sequence/version number 2 N
				//Not validated against type of carrier yet. Might need to check if Dentaide.
				strb.Append(TidyN(insPlan.DentaideCardSequence,2));
				//E18 secondary coverage flag 1 A
				if(planNum2>0) {
					strb.Append("Y");
				}
				else {
					strb.Append("N");
				}
				//E20 secondary record count 1 N
				if(planNum2==0) {
					strb.Append("0");
				}
				else {
					strb.Append("1");
				}
				//F06 number of procedures performed 1 N. Must be between 1 and 7.  UI prevents attaching more than 7.
				strb.Append(TidyN(claimProcsClaim.Count,1));//number validated
				//F22 extracted teeth count 2 N
				strb.Append(TidyN(extracted.Count,2));//validated against matching prosthesis
				if(claim.ClaimType=="PreAuth") {
					orthoRecordFlag=(claim.CanadaEstTreatStartDate.Year>1880 || claim.CanadaInitialPayment!=0 || claim.CanadaPaymentMode!=0 ||
						claim.CanadaTreatDuration!=0 || claim.CanadaNumAnticipatedPayments!=0 || claim.CanadaAnticipatedPayAmount!=0);
					//F25 Orthodontic Record Flag 1 N
					if(orthoRecordFlag) {
						strb.Append("1");
					}
					else {
						strb.Append("0");
					}
				}
				if(claim.ClaimType=="S") { //cob
					//G39 Embedded Transaction Length N 4
					strb.Append(Canadian.TidyN(primaryEOBResponse.Length,4));
				}
			}
			//Secondary carrier fields (E19 to E07) ONLY included if E20=1----------------------------------------------------
			if(planNum2!=0) {
				if(carrier.CDAnetVersion!="02") { //version 04
					//E19 secondary carrier transaction number 6 N
					strb.Append(TidyN(etrans.CarrierTransCounter2,6));
				}
				//E01 sec carrier id number 6 N
				strb.Append(carrier2.ElectID);//already validated as 6 digit number.
				if(carrier.CDAnetVersion=="02") {
					//E02 sec carrier policy/plan num 8 AN
					//only validated to ensure that it's not blank and is less than 8. Also that no spaces.
					//We might later allow 999999 if sec carrier is unlisted or unknown.
					strb.Append(TidyAN(insPlan2.GroupNum,8));
				}
				else { //version 04
					//E02 sec carrier policy/plan num 12 AN
					//only validated to ensure that it's not blank and is less than 12. Also that no spaces.
					//We might later allow 999999 if sec carrier is unlisted or unknown.
					strb.Append(TidyAN(insPlan2.GroupNum,12));
				}
				//E05 sec division/section num 10 AN
				strb.Append(TidyAN(insPlan2.DivisionNo,10));
				if(carrier.CDAnetVersion=="02") {
					//E03 sec plan subscriber id 11 AN
					strb.Append(TidyAN(insSub2.SubscriberID.Replace("-",""),11));//validated
				}
				else { //version 04
					//E03 sec plan subscriber id 12 AN
					strb.Append(TidyAN(insSub2.SubscriberID.Replace("-",""),12));//validated
				}
				if(carrier.CDAnetVersion!="02") { //version 04
					//E17 sec dependent code 2 N
					string patID="";
					for(int p=0;p<patPlansForPatient.Count;p++) {
						if(patPlansForPatient[p].InsSubNum==insSubNum2) {
							patID=patPlansForPatient[p].PatID;
						}
					}
					strb.Append(TidyN(patID,2));
					//E06 sec relationship code 1 N
					//User interface does not only show Canadian options, but all options are handled.
					strb.Append(GetRelationshipCode(patRelat2));
				}
				//E04 sec subscriber birthday 8 N
				strb.Append(claim.ClaimType=="S"?primaryClaimData.GetFieldById("E04").valuestr:subscriber2.Birthdate.ToString("yyyyMMdd"));//validated
				if(carrier.CDAnetVersion!="02") { //version 04
					//E08 sec subscriber last name 25 AE
					strb.Append(TidyAE(claim.ClaimType=="S"?primaryClaimData.GetFieldById("E08").valuestr:subscriber2.LName,25,true));//validated
					//E09 sec subscriber first name 15 AE
					strb.Append(TidyAE(claim.ClaimType=="S"?primaryClaimData.GetFieldById("E09").valuestr:subscriber2.FName,15,true));//validated
					//E10 sec subscriber middle initial 1 AE
					strb.Append(TidyAE(claim.ClaimType=="S"?primaryClaimData.GetFieldById("E10").valuestr:subscriber2.MiddleI,1));
					//E11 sec subscriber address one 30 AEN
					strb.Append(TidyAEN(claim.ClaimType=="S"?primaryClaimData.GetFieldById("E11").valuestr:subscriber2.Address,30,true));//validated
					//E12 sec subscriber address two 30 AEN
					strb.Append(TidyAEN(claim.ClaimType=="S"?primaryClaimData.GetFieldById("E12").valuestr:subscriber2.Address2,30,true));
					//E13 sec subscriber city 20 AEN
					strb.Append(TidyAEN(claim.ClaimType=="S"?primaryClaimData.GetFieldById("E13").valuestr:subscriber2.City,20,true));//validated
					//E14 sec subscriber province/state 2 A
					strb.Append(claim.ClaimType=="S"?primaryClaimData.GetFieldById("E14").valuestr:subscriber2.State);//very throroughly validated previously
					//E15 sec subscriber postal/zip code 9 AN
					strb.Append(TidyAN(claim.ClaimType=="S"?primaryClaimData.GetFieldById("E15").valuestr:subscriber2.Zip.Replace("-","").Replace(" ",""),9));//validated
					//E16 sec language 1 A
					strb.Append(claim.ClaimType=="S"?primaryClaimData.GetFieldById("E16").valuestr:(subscriber2.Language=="fr"?"F":"E"));
					//E07 sec card sequence/version num 2 N
					//todo Not validated yet.
					strb.Append(TidyN(claim.ClaimType=="S"?PIn.Int(primaryClaimData.GetFieldById("E07").valuestr):insPlan2.DentaideCardSequence,2));
				}
				//End of secondary subscriber fields---------------------------------------------------------------------------
			}
			else { //There is no secondary plan.
				if(carrier.CDAnetVersion=="02") { 
					//Secondary subscriber fields are always available in version 2. Since there is no plan, put blank data as a filler.
					//E01 N 6
					strb.Append("000000");
					//E02 AN 8
					strb.Append("        ");
					//E05 AN 10
					strb.Append("          ");
					//E03 AN 11
					strb.Append("           ");
					//E04 N 8
					strb.Append("00000000");
				}
			}
			if(claim.ClaimType!="PreAuth") {
				//F01 payee code 1 N
				if((claim.ClaimType!="S" && insSub.AssignBen) || (claim.ClaimType=="S" && insSub2.AssignBen)) {
					if(carrier.CDAnetVersion=="02") {
						strb.Append("0");//pay dentist
					}
					else { //version 04
						strb.Append("4");//pay dentist
					}
				}
				else {
					strb.Append("1");//pay subscriber
				}
			}
			//F02 accident date 8 N
			if(claim.AccidentDate.Year>1900){//if accident related
				strb.Append(claim.AccidentDate.ToString("yyyyMMdd"));//validated
			}
			else{
				strb.Append(TidyN(0,8));
			}
			if(claim.ClaimType!="PreAuth") {
				//F03 predetermination number 14 AN
				strb.Append(TidyAN(claim.PreAuthString,14));
			}
			if(carrier.CDAnetVersion=="02") {
				//F15 Is this an Initial Replacement? A 1
				string initialPlacement="Y";
				DateTime initialPlacementDate=DateTime.MinValue;
				if(claim.CanadianIsInitialUpper=="Y"){
					initialPlacement="Y";
					initialPlacementDate=claim.CanadianDateInitialUpper;
				}
				else if(claim.CanadianIsInitialLower=="Y"){
					initialPlacement="Y";
					initialPlacementDate=claim.CanadianDateInitialLower;
				}
				else if(claim.CanadianIsInitialUpper=="N") {
					initialPlacement="N";
					initialPlacementDate=claim.CanadianDateInitialUpper;
				}
				else if(claim.CanadianIsInitialLower=="N"){
					initialPlacement="N";
					initialPlacementDate=claim.CanadianDateInitialLower;
				}
				strb.Append(initialPlacement);
				//F04 date of initial placement 8 N
				if(initialPlacementDate.Year>1900) {
					strb.Append(initialPlacementDate.ToString("yyyyMMdd"));
				}
				else {
					strb.Append("00000000");
				}
				//F05 tx req'd for ortho purposes 1 A
				if(claim.IsOrtho) {
					strb.Append("Y");
				}
				else {
					strb.Append("N");
				}
				//F06 number of procedures performed 1 N. Must be between 1 and 7.  UI prevents attaching more than 7.
				strb.Append(TidyN(claimProcsClaim.Count,1));//number validated
			}
			else { //version 04
				//F15 initial placement upper 1 A  Y or N or X
				strb.Append(Canadian.TidyA(claim.CanadianIsInitialUpper,1));//validated
				//F04 date of initial placement upper 8 N
				if(claim.CanadianDateInitialUpper.Year>1900) {
					strb.Append(claim.CanadianDateInitialUpper.ToString("yyyyMMdd"));
				}
				else {
					strb.Append("00000000");
				}
				//F18 initial placement lower 1 A
				strb.Append(Canadian.TidyA(claim.CanadianIsInitialLower,1));//validated
				//F19 date of initial placement lower 8 N
				if(claim.CanadianDateInitialLower.Year>1900) {
					strb.Append(claim.CanadianDateInitialLower.ToString("yyyyMMdd"));
				}
				else {
					strb.Append("00000000");
				}
				//F05 tx req'd for ortho purposes 1 A
				if(claim.IsOrtho) {
					strb.Append("Y");
				}
				else {
					strb.Append("N");
				}
				//F20 max prosth material 1 N
				if(claim.CanadianMaxProsthMaterial==7) {//our fake crown code
					strb.Append("0");
				}
				else {
					strb.Append(claim.CanadianMaxProsthMaterial.ToString());//validated
				}
				//F21 mand prosth material 1 N
				if(claim.CanadianMandProsthMaterial==7) {//our fake crown code
					strb.Append("0");
				}
				else {
					strb.Append(claim.CanadianMandProsthMaterial.ToString());//validated
				}
			}
			if(carrier.CDAnetVersion!="02") { //version 04
				//If F22 is non-zero. Repeat for the number of times specified by F22.----------------------------------------------
				for(int t=0;t<extracted.Count;t++) {
					//F23 extracted tooth num 2 N
					//todo: check validation
					strb.Append(TidyN(Tooth.ToInternat(extracted[t].ToothNum),2));//validated
					//F24 extraction date 8 N
					//todo: check validation
					strb.Append(extracted[t].ProcDate.ToString("yyyyMMdd"));//validated
				}
			}
			if(carrier.CDAnetVersion!="02") { //version 04
				if(claim.ClaimType=="PreAuth") {
#if DEBUG
					//We are required to test multi-page (up to 7 procs per page) predeterminations for certification. We do not actually do this in the real world.
					//We will use the claim.PreAuthString here to pass these useless numbers in for testing purposes, since this field is not used for predetermination claims for any other reason.
					int currentPredeterminationPageNumber=1;
					int lastPredeterminationPageNumber=1;
					if(claim.PreAuthString!="") {
						string[] predetermNums=claim.PreAuthString.Split(new char[] { ',' });
						currentPredeterminationPageNumber=PIn.Int(predetermNums[0]);
						lastPredeterminationPageNumber=PIn.Int(predetermNums[1]);
					}
					//G46 Current Predetermination Page Number N 1
					strb.Append(Canadian.TidyN(currentPredeterminationPageNumber,1));
					//G47 Last Predetermination Page Number N 1
					strb.Append(Canadian.TidyN(lastPredeterminationPageNumber,1));
#else
					//G46 Current Predetermination Page Number N 1
					strb.Append("1");//Always 1 page, because UI prevents attaching more than 7 procedures per claim in Canadian mode.
					//G47 Last Predetermination Page Number N 1
					strb.Append("1");//Always 1 page, because UI prevents attaching more than 7 procedures per claim in Canadian mode.
#endif
					if(orthoRecordFlag) { //F25 is set
						//F37 Estimated Treatment Starting Date N 8
						strb.Append(Canadian.TidyN(claim.CanadaEstTreatStartDate.ToString("yyyyMMdd"),8));
						double firstExamFee=0;
						double diagnosticPhaseFee=0;
#if DEBUG //Fields F26 and F27 are not required in the real world, but there are a few certification tests that require this information in order for the test to pass.
						if(claim.PreAuthString!="") {
							string[] preauthData=claim.PreAuthString.Split(new char[] { ',' });
							if(preauthData.Length>2) {
								firstExamFee=PIn.Double(preauthData[2]);
							}
							if(preauthData.Length>3) {
								diagnosticPhaseFee=PIn.Double(preauthData[3]);
							}
						}
#endif
						//F26 First Examination Fee D 6
						strb.Append(Canadian.TidyD(firstExamFee,6));//optional
						//F27 Diagnostic Phase Fee D 6
						strb.Append(Canadian.TidyD(diagnosticPhaseFee,6));//optional
						//F28 Initial Payment D 6
						strb.Append(Canadian.TidyD(claim.CanadaInitialPayment,6));
						//F29 Payment Mode N 1
						strb.Append(Canadian.TidyN(claim.CanadaPaymentMode,1));//Validated in UI.
						//F30 Treatment Duration N 2
						strb.Append(Canadian.TidyN(claim.CanadaTreatDuration,2));
						//F31 Number of Anticipated Payments N 2
						strb.Append(Canadian.TidyN(claim.CanadaNumAnticipatedPayments,2));
						//F32 Anticipated Payment Amount D 6
						strb.Append(Canadian.TidyD(claim.CanadaAnticipatedPayAmount,6));
					}
				}
			}
			//Procedures: Repeat for number of times specified by F06.----------------------------------------------------------
			for(int p=0;p<claimProcsClaim.Count;p++) {
				//claimProcsClaim already excludes any claimprocs with ProcNum=0, so no payments etc.
				proc=Procedures.GetProcFromList(procListAll,claimProcsClaim[p].ProcNum);
				procCode=ProcedureCodes.GetProcCode(proc.CodeNum);
				procListLabForOne=Procedures.GetCanadianLabFees(proc.ProcNum,procListAll);
				//F07 proc line number 1 N
				strb.Append((p+1).ToString());
				if(carrier.CDAnetVersion=="02") {
					//F08 procedure code 5 N
					strb.Append(TidyN(claimProcsClaim[p].CodeSent,5).Trim().PadLeft(5,'0'));
				}
				else { //version 04
					//F08 procedure code 5 AN
					strb.Append(TidyAN(claimProcsClaim[p].CodeSent,5).Trim().PadLeft(5,'0'));
				}
				if(claim.ClaimType!="PreAuth") {
					//F09 date of service 8 N
					strb.Append(claimProcsClaim[p].ProcDate.ToString("yyyyMMdd"));//validated
				}
				//F10 international tooth, sextant, quad, or arch 2 N
				strb.Append(GetToothQuadOrArch(proc,procCode));
				//F11 tooth surface 5 A
				//the SurfTidy function is very thorough, so it's OK to use TidyAN
				if(procCode.TreatArea==TreatmentArea.Surf) {
#if DEBUG
					//since the scripts use impossible surfaces, we need to just use raw database here
					strb.Append(TidyAN(proc.Surf,5));
#else
					strb.Append(TidyAN(Tooth.SurfTidyForClaims(proc.Surf,proc.ToothNum),5));
#endif
				}
				else {
					strb.Append("     ");
				}
				//F12 dentist's fee claimed 6 D
				strb.Append(TidyD(claimProcsClaim[p].FeeBilled,6));
				if(carrier.CDAnetVersion!="02") { //version 04
					//F34 lab procedure code #1 5 AN
					if(procListLabForOne.Count>0) {
						strb.Append(TidyAN(ProcedureCodes.GetProcCode(procListLabForOne[0].CodeNum).ProcCode,5).Trim().PadLeft(5,'0'));
					}
					else {
						strb.Append("     ");
					}
				}
				//F13 lab procedure fee #1 6 D
				if(procListLabForOne.Count>0){
					strb.Append(TidyD(procListLabForOne[0].ProcFee,6));
				}
				else{
					strb.Append("000000");
				}
				if(carrier.CDAnetVersion=="02") {
					//F14 Unit of Time D 4
					//This is a somewhat deprecated field becacuse it no longer exists in version 04. Some carriers reject claims 
					//if there is a time specified for a procedure that does not require a time. It is safest for now to just set
					//this value to zero always.
					double procHours=0;
					//procHours=(PrefC.GetInt(PrefName.AppointmentTimeIncrement)*procCode.ProcTime.Length)/60.0;
					strb.Append(TidyD(procHours,4));
				}
				else { //version 04
					//F35 lab procedure code #2 5 AN
					if(procListLabForOne.Count>1) {
						strb.Append(TidyAN(ProcedureCodes.GetProcCode(procListLabForOne[1].CodeNum).ProcCode,5).Trim().PadLeft(5,'0'));
					}
					else {
						strb.Append("     ");
					}
					//F36 lab procedure fee #2 6 D
					if(procListLabForOne.Count>1) {
						strb.Append(TidyD(procListLabForOne[1].ProcFee,6));
					}
					else {
						strb.Append("000000");
					}
					//F16 procedure type codes 5 A
					strb.Append(TidyA((proc.CanadianTypeCodes==null || proc.CanadianTypeCodes=="")?"X":proc.CanadianTypeCodes,5));
					//F17 remarks code 2 N
					//optional.  PMP field.  See C12. Zeros when not used.
					strb.Append("00");
				}
			}
			if(carrier.CDAnetVersion!="02") { //version 04
				//C19 plan record 30 AN
				if(C19PlanRecordPresent) {
					if(insPlan.CanadianPlanFlag=="A") {
						//insPlan.CanadianDiagnosticCode and insPlan.CanadianInstitutionCode are validated in the UI.
						strb.Append(Canadian.TidyAN(Canadian.TidyAN(insPlan.CanadianDiagnosticCode,6,true)+Canadian.TidyAN(insPlan.CanadianInstitutionCode,6,true),30,true));
					}
					else { //N or V. These two plan flags are not yet in use. Presumably, for future use.
						strb.Append(Canadian.TidyAN("",30));
					}
				}
			}
			//We are required to append the primary EOB. This is not a data dictionary field.
			if(claim.ClaimType=="S") {
				strb.Append(ConvertEOBVersion(primaryEOBResponse,carrier.CDAnetVersion));
			}
			//Now we go back and fill in the actual message length now that we know the number for sure.
			if(carrier.CDAnetVersion=="02") {
				strb.Replace("0000",Canadian.TidyN(strb.Length,4),31,4);
			}
			else { //version 04
				strb.Replace("00000",Canadian.TidyN(strb.Length,5),32,5);
			}
			//end of creating the message
			//this is where we attempt the actual sending:
			string result="";
			bool resultIsError=false;
			try{
#if DEBUG
				if(claim.ClaimType=="PreAuth") { //Predeterminations
					if(testNumber==3) { //Predetermination test #3
						strb.Replace("Y","N",563,1);//We use claim.IsOrtho for fields F05 and F25, but for some reason in this example the values expected are opposite. We think this is a problem with the CDANet test.
						strb.Replace("00000000","35000025",577,8);//These are optional fields (F26 and F27), so we have not implemented them, but the test does not work without them for some reason.
					}
				}
#endif
				result=PassToIca(strb.ToString(),clearhouse);
			}
			catch(ApplicationException ex) {
				result=ex.Message;
				resultIsError=true;
			}
			//Attach an ack to the etrans
			Etrans etransAck=new Etrans();
			etransAck.PatNum=etrans.PatNum;
			etransAck.PlanNum=etrans.PlanNum;
			etransAck.InsSubNum=etrans.InsSubNum;
			etransAck.CarrierNum=etrans.CarrierNum;
			etransAck.ClaimNum=etrans.ClaimNum;
			etransAck.DateTimeTrans=DateTime.Now;
			CCDFieldInputter fieldInputter=null;
			if(resultIsError){
				etransAck.Etype=EtransType.AckError;
				etrans.Note="failed";
			}
			else{
				fieldInputter=new CCDFieldInputter(result);
				CCDField fieldG05=fieldInputter.GetFieldById("G05");
				if(fieldG05!=null) {
					etransAck.AckCode=fieldG05.valuestr;
					if(etransAck.AckCode=="M") { //Manually print the claim form.
						PrintCdaClaimForm(claim);
					}
				}
				etransAck.Etype=fieldInputter.GetEtransType();
			}
			Etranss.Insert(etransAck);
			Etranss.SetMessage(etransAck.EtransNum,result);
			etrans.AckEtransNum=etransAck.EtransNum;
			Etranss.Update(etrans);
			Etranss.SetMessage(etrans.EtransNum,strb.ToString());
			if(resultIsError) {
				throw new ApplicationException(result);
			}
			if(claim.ClaimType!="PreAuth") {
				Claims.SetCanadianClaimSent(queueItem.ClaimNum);//when called from ClaimEdit, that window will close immediately, so we're directly changing the db.
				CCDField fieldTransRefNum=fieldInputter.GetFieldById("G01");
				if(fieldTransRefNum!=null) {
					if(etransAck.AckCode!="R") {
						claim.CanadaTransRefNum=fieldTransRefNum.valuestr;
						Claims.Update(claim);
					}
				}
			}
			if(doPrint) {
				new FormCCDPrint(etrans,result,true);//Physically print the form.
			}
			if(claim.ClaimType!="PreAuth" && claim.ClaimType!="S" && etransAck.Etype==EtransType.ClaimEOB_CA && planNum2>0) {//if an eob was returned and patient has secondary insurance.
				//if an EOB is returned, there are two possibilities.
				//1. The EOB contains an embedded EOB because the same carrier is both pri and sec.  Both got printed above.
				//2. The EOB does not contain an embedded EOB, indicating that a COB claim needs to be created and sent.
				//That is done here, automatically.
				//UI already prevents the initial automatic creation of the secondary claim for Canada.
				string embeddedLength=fieldInputter.GetValue("G39");
				if(embeddedLength=="" || embeddedLength=="0000") {//no embedded message
					Claim claim2=new Claim();
					claim2.PatNum=claim.PatNum;
					claim2.DateService=claim.DateService;
					claim2.DateSent=DateTime.Today;
					claim2.ClaimStatus="W";
					claim2.PlanNum=planNum2;
					claim2.InsSubNum=insSubNum2;
					claim2.PatRelat=patRelat2;
					claim2.PlanNum2=planNum;
					claim2.InsSubNum2=insSubNum;
					claim2.PatRelat2=patRelat;
					claim2.ClaimType="S";
					claim2.ProvTreat=claim.ProvTreat;
					claim2.IsProsthesis="N";
					claim2.ProvBill=claim.ProvBill;
					claim2.EmployRelated=YN.No;
					claim2.AccidentDate=claim.AccidentDate;
					claim2.IsOrtho=claim.IsOrtho;
					claim2.CanadianDateInitialLower=claim.CanadianDateInitialLower;
					claim2.CanadianDateInitialUpper=claim.CanadianDateInitialUpper;
					claim2.CanadianIsInitialLower=claim.CanadianIsInitialLower;
					claim2.CanadianIsInitialUpper=claim.CanadianIsInitialUpper;
					claim2.CanadianMandProsthMaterial=claim.CanadianMandProsthMaterial;
					claim2.CanadianMaterialsForwarded=claim.CanadianMaterialsForwarded;
					claim2.CanadianMaxProsthMaterial=claim.CanadianMaxProsthMaterial;
					claim2.CanadianReferralProviderNum=claim.CanadianReferralProviderNum;
					claim2.CanadianReferralReason=claim.CanadianReferralReason;
					Claims.Insert(claim2);//to retreive a key for new Claim.ClaimNum
					ClaimProc[] claimProcsClaim2=new ClaimProc[claimProcsClaim.Count];
					long procNum;
					for(int i=0;i<claimProcsClaim.Count;i++) {//loop through the procs from claim 1
						//and try to find an estimate that can be used
						procNum=claimProcsClaim[i].ProcNum;
						claimProcsClaim2[i]=Procedures.GetClaimProcEstimate(procNum,claimProcList,insPlan2,claim2.InsSubNum2);
					}
					for(int i=0;i<claimProcsClaim2.Length;i++) {//loop through each claimProc
						//and create any missing estimates just in case
						if(claimProcsClaim2[i]==null) {
							claimProcsClaim2[i]=new ClaimProc();
							//claimProcsClaim and claimProcsClaim2 already exclude any claimprocs with ProcNum=0, so no payments etc.
							proc=Procedures.GetProcFromList(procListAll,claimProcsClaim[i].ProcNum);
							ClaimProcs.CreateEst(claimProcsClaim2[i],proc,insPlan2,insSub2);
						}
					}
					for(int i=0;i<claimProcsClaim2.Length;i++) {
						//claimProcsClaim and claimProcsClaim2 already exclude any claimprocs with ProcNum=0, so no payments etc.
						proc=Procedures.GetProcFromList(procListAll,claimProcsClaim2[i].ProcNum);//1:1
						claimProcsClaim2[i].ClaimNum=claim2.ClaimNum;
						claimProcsClaim2[i].Status=ClaimProcStatus.NotReceived;
						claimProcsClaim2[i].CodeSent=claimProcsClaim[i].CodeSent;
						claimProcsClaim2[i].LineNumber=(byte)(i+1);
						ClaimProcs.Update(claimProcsClaim2[i]);
					}
					claimProcList=ClaimProcs.Refresh(claim2.PatNum);
					Family fam=Patients.GetFamily(claim2.PatNum);
					List<InsSub> subList=InsSubs.RefreshForFam(fam);
					List<InsPlan> planList=InsPlans.RefreshForSubList(subList);
					List<Benefit> benefitList=Benefits.Refresh(patPlansForPatient,subList);
					ClaimL.CalculateAndUpdate(procListAll,planList,claim2,patPlansForPatient,benefitList,patient.Age,subList);
					ClaimSendQueueItem queueItem2=Claims.GetQueueList(claim2.ClaimNum,claim2.ClinicNum,0)[0];
					string responseMessageVersion=result.Substring(18,2);//Field A03 always exists on all messages and is always in the same location.
					//ok to skip validation
					//We can only send an electronic secondary claim when the EOB received from the primary insurance is a version 04 message and when
					//the secondary carrier accepts secondary claims electronically (COBs). Otherwise, the user must send the claim by paper.
					if(responseMessageVersion!="02" && (carrier2.CanadianSupportedTypes&CanSupTransTypes.CobClaimTransaction_07)==CanSupTransTypes.CobClaimTransaction_07) {
						long etransNum=SendClaim(queueItem2,doPrint);//recursive
						return etransNum;//for now, we'll return the etransnum of the secondary ack.
					}
					//The secondary carrier does not support COB claim transactions. We must print a manual claim form.
					if(doPrint) {
						PrintCdaClaimForm(claim2);
					}
				}
				else {//an embedded message exists
					//string embeddedMsg=fieldInputter.GetValue("G40");
					//MsgBoxCopyPaste msgbox=new MsgBoxCopyPaste(embeddedMsg);
					//msgbox.Show();
					//actually, nothing to do here because already printed above.
				}
			}
			return etransAck.EtransNum;
		}
コード例 #23
0
ファイル: Etranss.cs プロジェクト: ChemBrain/OpenDental
		///<summary>Throws exceptions.
		///When etrans.Etype is associated to a Canadian request EType, this runs multiple queries to set etrans.CarrierTransCounter and
		///etrans.CarrierTransCounter2.  Otherwise returns without making any changes.
		///The etrans.CarrierNum, etrans.CarrierNum2 and etrans.Etype columns must be set prior to running this.</summary>
		public static Etrans SetCanadianEtransFields(Etrans etrans,bool hasSecondary=true) {
			if(!etrans.Etype.GetAttributeOrDefault<EtransTypeAttr>().IsCanadaType || !etrans.Etype.GetAttributeOrDefault<EtransTypeAttr>().IsRequestType) {
				return etrans;
			}
			if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
				return Meth.GetObject<Etrans>(MethodBase.GetCurrentMethod(),etrans,hasSecondary);
			}
			etrans.OfficeSequenceNumber=0;
			//find the next officeSequenceNumber
			string command="SELECT MAX(OfficeSequenceNumber) FROM etrans";
			DataTable 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.");
				}
			}
			etrans.OfficeSequenceNumber++;
			//find the next CarrierTransCounter for the primary carrier
			#region CarrierTransCounter
			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.");
				//maybe by adding a reset date to the preference table which will apply to all counters as a whole.
			}
			etrans.CarrierTransCounter++;
			#endregion CarrierTransCounter
			if(!hasSecondary || etrans.CarrierNum2==0) {
				return etrans;
			}
			#region CarrierTransCounter2
			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++;
			#endregion
			return etrans;
		}
コード例 #24
0
ファイル: Etranss.cs プロジェクト: nampn/ODental
 ///<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, and it doesn't actually set the claim as sent.  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.
 }
コード例 #25
0
ファイル: Etranss.cs プロジェクト: romeroyonatan/opendental
		///<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);
			}
		}
コード例 #26
0
ファイル: Etranss.cs プロジェクト: nampn/ODental
 ///<summary></summary>
 public static void Update(Etrans etrans)
 {
     if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
         Meth.GetVoid(MethodBase.GetCurrentMethod(),etrans);
         return;
     }
     Crud.EtransCrud.Update(etrans);
 }
コード例 #27
0
ファイル: Etranss.cs プロジェクト: ChemBrain/OpenDental
		public static void Delete835(Etrans etrans) {
			EtransMessageTexts.Delete(etrans.EtransMessageTextNum,etrans.EtransNum);
			Etranss.Delete(etrans.EtransNum);
			Etrans835Attaches.DeleteMany(-1,etrans.EtransNum);
		}
コード例 #28
0
ファイル: Etranss.cs プロジェクト: steev90/opendental
        ///<summary>Not for claim types, just other types, including Eligibility. This function gets run first.  Then, the messagetext is created and an attempt is made to send the message.  Finally, the messagetext is added to the etrans.  This is necessary because the transaction numbers must be incremented and assigned to each message before creating the message and attempting to send.  If it fails, we will need to roll back.  Provide EITHER a carrierNum OR a canadianNetworkNum.  Many transactions can be sent to a carrier or to a network.</summary>
        public static Etrans CreateCanadianOutput(long patNum, long carrierNum, long canadianNetworkNum, long clearinghouseNum, EtransType etype, long planNum, long insSubNum)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                return(Meth.GetObject <Etrans>(MethodBase.GetCurrentMethod(), patNum, carrierNum, canadianNetworkNum, clearinghouseNum, etype, planNum, insSubNum));
            }
            //validation of carrier vs network
            if (etype == EtransType.Eligibility_CA)
            {
                //only carrierNum is allowed (and required)
                if (carrierNum == 0)
                {
                    throw new ApplicationException("Carrier not supplied for Etranss.CreateCanadianOutput.");
                }
                if (canadianNetworkNum != 0)
                {
                    throw new ApplicationException("NetworkNum not allowed for Etranss.CreateCanadianOutput.");
                }
            }
            Etrans etrans = new Etrans();

            //etrans.DateTimeTrans handled automatically
            etrans.ClearingHouseNum = clearinghouseNum;
            etrans.Etype            = etype;
            etrans.ClaimNum         = 0;  //no claim involved
            etrans.PatNum           = patNum;
            //CanadianNetworkNum?
            etrans.CarrierNum = carrierNum;
            etrans.PlanNum    = planNum;
            etrans.InsSubNum  = insSubNum;
            //Get next OfficeSequenceNumber-----------------------------------------------------------------------------------------
            etrans.OfficeSequenceNumber = 0;
            string    command = "SELECT MAX(OfficeSequenceNumber) FROM etrans";
            DataTable 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.
                //get the date of the most recent max
                //This works, but it got even more complex for CarrierTransCounter, so we will just throw an exception for now.

                /*command="SELECT MAX(DateTimeTrans) FROM etrans WHERE OfficeSequenceNumber=999999";
                 * table=Db.GetTable(command);
                 * DateTime maxDateT=PIn.PDateT(table.Rows[0][0].ToString());
                 * //then, just get the max that's newer than that.
                 * command="SELECT MAX(OfficeSequenceNumber) FROM etrans WHERE DateTimeTrans > '"+POut.PDateT(maxDateT)+"'";
                 * table=Db.GetTable(command);
                 * if(table.Rows.Count>0) {
                 *      etrans.OfficeSequenceNumber=PIn.PInt(table.Rows[0][0].ToString());
                 * }*/
                {
                    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++;
            //if(etype==EtransType.Eligibility_CA){ //The counter must be incremented for all transaction types, according to the documentation for field A09 Carrier Transaction Counter.
            //find the next CarrierTransCounter------------------------------------------------------------------------------------
            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.");
                //maybe by adding a reset date to the preference table which will apply to all counters as a whole.
            }
            etrans.CarrierTransCounter++;
            //}
            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.
        }
コード例 #29
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.
        }
コード例 #30
0
ファイル: Etranss.cs プロジェクト: steev90/opendental
        ///<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);
            }
        }
コード例 #31
0
ファイル: FormEtransEdit.cs プロジェクト: nampn/ODental
 private void FormEtransEdit_Load(object sender,EventArgs e)
 {
     MessageText=EtransMessageTexts.GetMessageText(EtransCur.EtransMessageTextNum);
     textMessageText.Text=MessageText;
     textDateTimeTrans.Text=EtransCur.DateTimeTrans.ToString();
     textClaimNum.Text=EtransCur.ClaimNum.ToString();
     textBatchNumber.Text=EtransCur.BatchNumber.ToString();
     textTransSetNum.Text=EtransCur.TransSetNum.ToString();
     textAckCode.Text=EtransCur.AckCode;
     textNote.Text=EtransCur.Note;
     if(EtransCur.Etype==EtransType.ClaimSent){
         if(X12object.IsX12(MessageText)) {
             //TODO: we need to do something different here for 5010s.
             X837_4010 x837=new X837_4010(MessageText);
             checkAttachments.Checked=x837.AttachmentsWereSent(EtransCur.ClaimNum);
         }
     }
     if(EtransCur.AckEtransNum>0){
         AckCur=Etranss.GetEtrans(EtransCur.AckEtransNum);
         if(AckCur!=null){
             textAckMessage.Text=EtransMessageTexts.GetMessageText(AckCur.EtransMessageTextNum);
             textAckDateTime.Text=AckCur.DateTimeTrans.ToString();
         }
         groupAck.Text=Lan.g(this,"Acknowledgement");
     }
     else{
         AckCur=null;
         groupAck.Visible=false;
     }
     if(!CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Not Canadian.
         butPrintAck.Visible=false;
     }
 }
コード例 #32
0
ファイル: FormEtransEdit.cs プロジェクト: mnisl/OD
		private void FormEtransEdit_Load(object sender,EventArgs e) {
			MessageText=EtransMessageTexts.GetMessageText(EtransCur.EtransMessageTextNum);
			textMessageText.Text=MessageText;
			textDateTimeTrans.Text=EtransCur.DateTimeTrans.ToString();
			textClaimNum.Text=EtransCur.ClaimNum.ToString();
			textBatchNumber.Text=EtransCur.BatchNumber.ToString();
			textTransSetNum.Text=EtransCur.TransSetNum.ToString();
			textAckCode.Text=EtransCur.AckCode;
			textNote.Text=EtransCur.Note;
			if(EtransCur.Etype==EtransType.ClaimSent){
				if(X12object.IsX12(MessageText)) {
					X12object x12obj=new X12object(MessageText);
					if(x12obj.IsFormat4010()) {
						X837_4010 x837=new X837_4010(MessageText);
						checkAttachments.Checked=x837.AttachmentsWereSent(EtransCur.ClaimNum);//This function does not currently work, so the corresponding checkbox is hidden on the form as well.
					}
					else if(x12obj.IsFormat5010()) {
						X837_5010 x837=new X837_5010(MessageText);
						checkAttachments.Checked=x837.AttachmentsWereSent(EtransCur.ClaimNum);//This function does not currently work, so the corresponding checkbox is hidden on the form as well.
					}
				}
			}
			if(EtransCur.AckEtransNum>0){
				AckCur=Etranss.GetEtrans(EtransCur.AckEtransNum);
				if(AckCur!=null){
					textAckMessage.Text=EtransMessageTexts.GetMessageText(AckCur.EtransMessageTextNum);
					textAckDateTime.Text=AckCur.DateTimeTrans.ToString();
				}
				groupAck.Text=Lan.g(this,"Acknowledgement");
			}
			else{
				AckCur=null;
				groupAck.Visible=false;
			}
			if(!CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Not Canadian.
				butPrintAck.Visible=false;
			}
		}
コード例 #33
0
ファイル: CanadianOutput.cs プロジェクト: nampn/ODental
 ///<summary>Returns the list of etrans requests. The etrans.AckEtransNum can be used to get the etrans ack. The following are the only possible formats that can be returned in the acks: 21 EOB Response, 11 Claim Ack, 14 Outstanding Transactions Response, 23 Predetermination EOB, 13 Predetermination Ack, 24 E-Mail Response. Set version2 to true if version 02 request and false for version 04 request. Set sendToItrans to true only when sending to carrier 999999 representing the entire ITRANS network. When version2 is false and sendToItrans is false then carrier must be set to a valid Canadian carrier, otherwise it can be set to null. Prov must be validated as a CDANet provider before calling this function.</summary>
 public static List<Etrans> GetOutstandingTransactions(bool version2,bool sendToItrans,Carrier carrier,Provider prov)
 {
     List<Etrans> etransAcks=new List<Etrans>();
     Clearinghouse clearhouse=Canadian.GetClearinghouse();
     if(clearhouse==null) {
         throw new ApplicationException("Canadian clearinghouse not found.");
     }
     string saveFolder=clearhouse.ExportPath;
     if(!Directory.Exists(saveFolder)) {
         throw new ApplicationException(saveFolder+" not found.");
     }
     //We are required to send the request for outstanding transactions over and over until we get back an outstanding transactions ack format (Transaction type 14), because
     //there may be more than one item in the mailbox and we can only get one item at time.
     bool exit=false;
     do {
         StringBuilder strb=new StringBuilder();
         Etrans etrans=null;
         if(version2 || sendToItrans) {
             etrans=Etranss.CreateCanadianOutput(0,0,0,clearhouse.ClearinghouseNum,EtransType.RequestOutstand_CA,0,0);
         }
         else {
             if((carrier.CanadianSupportedTypes&CanSupTransTypes.RequestForOutstandingTrans_04)!=CanSupTransTypes.RequestForOutstandingTrans_04) {
                 throw new ApplicationException("The carrier does not support request for outstanding transactions.");
             }
             etrans=Etranss.CreateCanadianOutput(0,carrier.CarrierNum,carrier.CanadianNetworkNum,
                 clearhouse.ClearinghouseNum,EtransType.RequestOutstand_CA,0,0);
         }
         //A01 transaction prefix 12 AN
         if(version2 || sendToItrans) {
             strb.Append("            ");
         }
         else {
             if(carrier.CanadianNetworkNum==0) {
                 throw new ApplicationException("Carrier network not set.");
             }
             CanadianNetwork network=CanadianNetworks.GetNetwork(carrier.CanadianNetworkNum);
             strb.Append(Canadian.TidyAN(network.CanadianTransactionPrefix,12));
         }
         //A02 office sequence number 6 N
         strb.Append(Canadian.TidyN(etrans.OfficeSequenceNumber,6));
         //A03 format version number 2 N
         if(version2) {
             strb.Append("02");
         }
         else {
             strb.Append("04");
         }
         //A04 transaction code 2 N
         strb.Append("04");//outstanding transactions request
         if(!version2) {//version 04
             //A05 carrier id number 6 N
             if(sendToItrans) {
                 strb.Append("999999");
             }
             else {
                 strb.Append(carrier.ElectID);//already validated as 6 digit number.
             }
         }
         //A06 software system id 3 AN
         strb.Append(Canadian.SoftwareSystemId());
         if(!version2) { //version 04
             //A10 encryption method 1 N
             if(sendToItrans) {
                 strb.Append("1");
             }
             else {
                 strb.Append(carrier.CanadianEncryptionMethod);//validated in UI
             }
         }
         //A07 message length N4
         if(!version2) { //version 04
             strb.Append(Canadian.TidyN("64",5));
         }
         else {
             strb.Append(Canadian.TidyN("42",4));
         }
         if(!version2) { //version 04
             //A09 carrier transaction counter 5 N
             strb.Append(Canadian.TidyN(etrans.CarrierTransCounter,5));
         }
         //According to the documentation for the outstanding transactions ack format, B01 only has to be a valid provider for the practice,
         //and that will trigger acknowledgements for all providers of the practice. I am assuming here that the same is true for the
         //billing provider in field B03, because there is no real reason to limit the request to any particular provider.
         //B01 CDA provider number 9 AN
         strb.Append(Canadian.TidyAN(prov.NationalProvID,9));//already validated
         //B02 (treating) provider office number 4 AN
         strb.Append(Canadian.TidyAN(prov.CanadianOfficeNum,4));//already validated
         if(!version2) { //version 04
             //B03 billing provider number 9 AN
             //might need to account for possible 5 digit prov id assigned by carrier
             strb.Append(Canadian.TidyAN(prov.NationalProvID,9));//already validated
         }
         string result="";
         bool resultIsError=false;
         try {
             result=Canadian.PassToIca(strb.ToString(),clearhouse);
         }
         catch(ApplicationException ex) {
             result=ex.Message;
             resultIsError=true;
             //Etranss.Delete(etrans.EtransNum);//we don't want to do this, because we want the incremented etrans.OfficeSequenceNumber to be saved
             //Attach an ack indicating failure.
         }
         //Attach an ack to the etrans
         Etrans etransAck=new Etrans();
         etransAck.PatNum=etrans.PatNum;
         etransAck.PlanNum=etrans.PlanNum;
         etransAck.InsSubNum=etrans.InsSubNum;
         etransAck.CarrierNum=etrans.CarrierNum;
         etransAck.DateTimeTrans=DateTime.Now;
         CCDFieldInputter fieldInputter=null;
         if(resultIsError) {
             etransAck.Etype=EtransType.AckError;
             etrans.Note="failed";
         }
         else {
             if(result.Substring(12).StartsWith("NO MORE ITEMS")) {
                 etransAck.Etype=EtransType.OutstandingAck_CA;
                 exit=true;
             }
             else {
                 fieldInputter=new CCDFieldInputter(result);
                 CCDField fieldG05=fieldInputter.GetFieldById("G05");
                 if(fieldG05!=null) {
                     etransAck.AckCode=fieldG05.valuestr;
                 }
                 etransAck.Etype=fieldInputter.GetEtransType();
             }
         }
         Etranss.Insert(etransAck);
         Etranss.SetMessage(etransAck.EtransNum,result);
         etrans.AckEtransNum=etransAck.EtransNum;
         Etranss.Update(etrans);
         Etranss.SetMessage(etrans.EtransNum,strb.ToString());
         etransAcks.Add(etransAck);
         if(resultIsError) {
             throw new ApplicationException(result);
         }
         if(fieldInputter==null) { //happens in version 02 when a terminating message containing the text "NO MORE ITEMS" is received.
             break;
         }
         CCDField fieldA04=fieldInputter.GetFieldById("A04");//message format
         if(version2) {
             //In this case, there are only 4 possible responses: EOB, Claim Ack, Claim Ack with an error code, or Claim Ack with literal "NO MORE ITEMS" starting at character 13.
             if(fieldA04.valuestr=="11") {
                 CCDField fieldG08=fieldInputter.GetFieldById("G08");
                 if(fieldG08!=null && (fieldG08.valuestr=="004" || fieldG08.valuestr=="049")) { //Exit conditions specified in the documentation.
                     etransAck.Etype=EtransType.OutstandingAck_CA;
                     exit=true;
                 }
             }
         }
         else { //version 04
             //Remember, the only allowed response transaction types are: 21 EOB Response, 11 Claim Ack, 14 Outstanding Transactions Response, 23 Predetermination EOB, 13 Predetermination Ack, 24 E-Mail Response
             if(fieldA04.valuestr=="14") {//Outstanding Transaction Ack Format
                 CCDField fieldG05=fieldInputter.GetFieldById("G05");//response status
                 if(fieldG05.valuestr=="R") { //We only expect the result to be 'R' or 'X' as specified in the documentation.
                     CCDField fieldG07=fieldInputter.GetFieldById("G07");//disposition message
                     CCDField fieldG08=fieldInputter.GetFieldById("G08");//error code
                     MessageBox.Show(Lan.g("","Failed to receive outstanding transactions. Messages from CDANet")+": "+Environment.NewLine+
                         fieldG07.valuestr.Trim()+Environment.NewLine+((fieldG08!=null)?CCDerror.message(Convert.ToInt32(fieldG08.valuestr),false):""));
                 }
                 etransAck.Etype=EtransType.OutstandingAck_CA;
                 exit=true;
             }
         }
         //Field A02 exists in all of the possible formats (21,11,14,23,13,24).
         CCDField fieldA02=fieldInputter.GetFieldById("A02");//office sequence number
         //We use the Office Sequence Number to find the original etrans entry so that we can discover which patient the response is referring to.
         Etrans etranOriginal=Etranss.GetForSequenceNumberCanada(fieldA02.valuestr);
         if(etranOriginal!=null) { //Null will happen when testing, but should not happen in production.
             etrans.PatNum=etranOriginal.PatNum;
             etrans.PlanNum=etranOriginal.PlanNum;
             etrans.InsSubNum=etranOriginal.InsSubNum;
             etrans.ClaimNum=etranOriginal.ClaimNum;
             Etranss.Update(etrans);
             etransAck.PatNum=etranOriginal.PatNum;
             etransAck.PlanNum=etranOriginal.PlanNum;
             etransAck.InsSubNum=etranOriginal.InsSubNum;
             etransAck.ClaimNum=etranOriginal.ClaimNum;
             Etranss.Update(etransAck);
             if(!exit) {
                 if(etransAck.ClaimNum!=0) {
                     Claim claim=Claims.GetClaim(etransAck.ClaimNum);
                     if(etransAck.AckCode=="A") {
                         claim.ClaimStatus="R";
                         claim.DateReceived=MiscData.GetNowDateTime();
                     }
                     else if(etransAck.AckCode=="H" || etransAck.AckCode=="B" || etransAck.AckCode=="C" || etransAck.AckCode=="N") {
                         claim.ClaimStatus="S";
                     }
                     else if(etransAck.AckCode=="M") {
                         Canadian.PrintManualClaimForm(claim);
                     }
                     Claims.Update(claim);
                 }
             }
         }
         if(!exit) {
             try {
                 new FormCCDPrint(etrans,result,true);
             }
             catch(Exception ex) {
                 MessageBox.Show(Lan.g("CanadianOutput","Failed to display one of the ROT responses")+": "+Environment.NewLine+ex.ToString());
             }
         }
     } while(!exit);
     return etransAcks;
 }
コード例 #34
0
		private static string Run(int scriptNum,Carrier carrier,CanadianNetwork network,Provider prov,out Etrans etrans,DateTime reconciliationDate) {
			string retVal="";
			etrans=CanadianOutput.GetSummaryReconciliation(carrier,network,prov,reconciliationDate);
			retVal+="Summary Reconciliation#"+scriptNum.ToString()+" successful.\r\n";
			return retVal;
		}
コード例 #35
0
ファイル: CanadianOutput.cs プロジェクト: nampn/ODental
 ///<summary>Each payment reconciliation request can return up to 9 pages. This function will return one etrans ack for each page in the result, since each page must be requested individually. Only for version 04, no such transaction exists for version 02. The provTreat and provBilling must be validated as CDANet providers before calling this function.</summary>
 public static List<Etrans> GetPaymentReconciliations(Carrier carrier,Provider provTreat,Provider provBilling,DateTime reconciliationDate)
 {
     Clearinghouse clearhouse=Canadian.GetClearinghouse();
     if(clearhouse==null) {
         throw new ApplicationException("Canadian clearinghouse not found.");
     }
     string saveFolder=clearhouse.ExportPath;
     if(!Directory.Exists(saveFolder)) {
         throw new ApplicationException(saveFolder+" not found.");
     }
     List<Etrans> etransAcks=new List<Etrans>();
     int pageNumber=1;
     int totalPages=1;
     do{
         StringBuilder strb=new StringBuilder();
         if((carrier.CanadianSupportedTypes&CanSupTransTypes.RequestForPaymentReconciliation_06)!=CanSupTransTypes.RequestForPaymentReconciliation_06) {
             throw new ApplicationException("The carrier does not support payment reconciliation transactions.");
         }
         if(carrier.CanadianNetworkNum==0) {
             throw new ApplicationException("Carrier network not set.");
         }
         CanadianNetwork network=CanadianNetworks.GetNetwork(carrier.CanadianNetworkNum);
         Etrans etrans=Etranss.CreateCanadianOutput(0,carrier.CarrierNum,carrier.CanadianNetworkNum,clearhouse.ClearinghouseNum,EtransType.RequestPay_CA,0,0);
         //A01 transaction prefix 12 AN
         strb.Append(Canadian.TidyAN(network.CanadianTransactionPrefix,12));
         //A02 office sequence number 6 N
         strb.Append(Canadian.TidyN(etrans.OfficeSequenceNumber,6));
         //A03 format version number 2 N
         strb.Append("04");
         //A04 transaction code 2 N
         strb.Append("06");//payment reconciliation request
         //A05 carrier id number 6 N
         if(network.CanadianIsRprHandler) {
             strb.Append("999999");//Always 999999 if the network handles the RPR requests instead of the carriers in the network.
         }
         else {
             strb.Append(carrier.ElectID);//already validated as 6 digit number.
         }
         //A06 software system id 3 AN
         strb.Append(Canadian.SoftwareSystemId());
         //A10 encryption method 1 N
         if(carrier!=null) {
             strb.Append(carrier.CanadianEncryptionMethod);//validated in UI
         }
         else {
             strb.Append("1");//No encryption when sending to a network.
         }
         //A07 message length N4
         strb.Append(Canadian.TidyN("77",5));
         //A09 carrier transaction counter 5 N
         strb.Append(Canadian.TidyN(etrans.CarrierTransCounter,5));
         //B01 CDA provider number 9 AN
         strb.Append(Canadian.TidyAN(provTreat.NationalProvID,9));//already validated
         //B02 (treating) provider office number 4 AN
         strb.Append(Canadian.TidyAN(provTreat.CanadianOfficeNum,4));//already validated
         //B03 billing provider number 9 AN
         //might need to account for possible 5 digit prov id assigned by carrier
         strb.Append(Canadian.TidyAN(provBilling.NationalProvID,9));//already validated
         //B04 billing provider office number 4 AN
         strb.Append(Canadian.TidyAN(provBilling.CanadianOfficeNum,4));//already validated
         //F33 Reconciliation Date 8 N
         strb.Append(reconciliationDate.ToString("yyyyMMdd"));
         //F38 Current Reconciliation Page Number N 1
         strb.Append(Canadian.TidyN(pageNumber,1));
         //End of message construction.
         string result="";
         bool resultIsError=false;
         try {
             result=Canadian.PassToIca(strb.ToString(),clearhouse);
         }
         catch(ApplicationException ex) {
             result=ex.Message;
             resultIsError=true;
             //Etranss.Delete(etrans.EtransNum);//we don't want to do this, because we want the incremented etrans.OfficeSequenceNumber to be saved
             //Attach an ack indicating failure.
         }
         //Attach an ack to the etrans
         Etrans etransAck=new Etrans();
         etransAck.PatNum=etrans.PatNum;
         etransAck.PlanNum=etrans.PlanNum;
         etransAck.InsSubNum=etrans.InsSubNum;
         etransAck.CarrierNum=etrans.CarrierNum;
         etransAck.DateTimeTrans=DateTime.Now;
         CCDFieldInputter fieldInputter=null;
         if(resultIsError) {
             etransAck.Etype=EtransType.AckError;
             etrans.Note="failed";
         }
         else {
             fieldInputter=new CCDFieldInputter(result);
             CCDField fieldG05=fieldInputter.GetFieldById("G05");
             if(fieldG05!=null) {
                 etransAck.AckCode=fieldG05.valuestr;
             }
             etransAck.Etype=fieldInputter.GetEtransType();
         }
         Etranss.Insert(etransAck);
         Etranss.SetMessage(etransAck.EtransNum,result);
         etrans.AckEtransNum=etransAck.EtransNum;
         Etranss.Update(etrans);
         Etranss.SetMessage(etrans.EtransNum,strb.ToString());
         etransAcks.Add(etransAck);
         if(resultIsError) {
             throw new ApplicationException(result);
         }
         CCDField fieldG62=fieldInputter.GetFieldById("G62");//Last reconciliation page number.
         totalPages=PIn.Int(fieldG62.valuestr);
         new FormCCDPrint(etrans,result,true);
         pageNumber++;
     } while(pageNumber<=totalPages);
     return etransAcks;
 }
コード例 #36
0
		///<summary>Only called internally.</summary>
		protected FormCCDPrint(Etrans pEtrans,string messageText,int pCopiesToPrint,bool pAutoPrint,bool pPatientCopy) {
			etrans=pEtrans;
			MessageText=messageText;
			copiesToPrint=pCopiesToPrint;
			autoPrint=pAutoPrint;
			patientCopy=pPatientCopy;
			Init();
		}
コード例 #37
0
ファイル: Etranss.cs プロジェクト: mnisl/OD
		///<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> listClaimIdentifiers=x277.GetClaimTrackingNumbers();
					for(int i=0;i<listClaimIdentifiers.Count;i++) {
						string claimIdentifier=listClaimIdentifiers[i];
						string[] arrayClaimInfo=x277.GetClaimInfo(claimIdentifier);
						string patFname=PIn.String(arrayClaimInfo[0]);
						string patLname=PIn.String(arrayClaimInfo[1]);
						DateTime dateServiceStart=PIn.DateT(arrayClaimInfo[6]);
						DateTime dateServiceEnd=PIn.DateT(arrayClaimInfo[7]);
						double claimFee=PIn.Double(arrayClaimInfo[9]);
						string subscriberId=PIn.String(arrayClaimInfo[10]);
						Claim claim=Claims.GetClaimFromX12(claimIdentifier,claimFee,dateServiceStart,dateServiceEnd,patFname,patLname,subscriberId);
						if(claim==null) {
							continue;
						}
						string ack=arrayClaimInfo[3];
						//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(claim.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 if(X835.Is835(Xobj)) {
					etrans.Etype=EtransType.ERA_835;
					List <string> listTranSetIds=Xobj.GetTranSetIds();
					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.
						}
						Etranss.Insert(etrans);
						X835 x835=new X835(messageText,etrans.TranSetId835);
						List<Hx835_Claim> listClaimEOBs=x835.ListClaimsPaid;
						for(int j=0;j<listClaimEOBs.Count;j++) {
							long claimNum=listClaimEOBs[j].ClaimNum;
							//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="+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);
			}
		}