Exemplo n.º 1
0
		///<summary>Called from Eclaims and includes multiple claims.  Returns the string that was sent.  The string needs to be parsed to determine the transaction numbers used for each claim.</summary>
		public static string SendBatch(List<ClaimSendQueueItem> queueItems,int batchNum,Clearinghouse clearhouse,EnumClaimMedType medType){
			//each batch is already guaranteed to be specific to one clearinghouse, one clinic, and one EnumClaimMedType
			//Clearinghouse clearhouse=ClearinghouseL.GetClearinghouse(queueItems[0].ClearinghouseNum);
			string saveFile=GetFileName(clearhouse,batchNum);
			if(saveFile==""){
				return "";
			}
			using(StreamWriter sw=new StreamWriter(saveFile,false,Encoding.ASCII)){
				if(clearhouse.Eformat==ElectronicClaimFormat.x837D_4010) {
					X837_4010.GenerateMessageText(sw,clearhouse,batchNum,queueItems);
				}
				else {//Any of the 3 kinds of 5010
					X837_5010.GenerateMessageText(sw,clearhouse,batchNum,queueItems,medType);
				}
			}
			if(clearhouse.CommBridge==EclaimsCommBridge.PostnTrack){
				//need to clear out all CRLF from entire file
				string strFile="";
				using(StreamReader sr=new StreamReader(saveFile,Encoding.ASCII)){
					strFile=sr.ReadToEnd();
				}
				strFile=strFile.Replace("\r","");
				strFile=strFile.Replace("\n","");
				using(StreamWriter sw=new StreamWriter(saveFile,false,Encoding.ASCII)){
					sw.Write(strFile);
				}
			}
			CopyToArchive(saveFile);
			return File.ReadAllText(saveFile);
		}
Exemplo n.º 2
0
        ///<summary>Returns true if the communications were successful, and false if they failed. If they failed, a rollback will happen automatically by deleting the previously created X12 file. The batchnum is supplied for the possible rollback.  Also used for mail retrieval.</summary>
        public static bool Launch(Clearinghouse clearinghouseClin, int batchNum, EnumClaimMedType medType)        //called from Eclaims.cs. Clinic-level clearinghouse passed in.
        {
            string batchFile = "";

            try {
                if (!Directory.Exists(clearinghouseClin.ExportPath))
                {
                    throw new ODException("Clearinghouse export path is invalid.");
                }
                //We make sure to only send the X12 batch file for the current batch, so that if there is a failure, then we know
                //for sure that we need to reverse the batch. This will also help us avoid any exterraneous/old batch files in the
                //same directory which might be left if there is a permission issue when trying to delete the batch files after processing.
                batchFile = Path.Combine(clearinghouseClin.ExportPath, "claims" + batchNum + ".txt");
                //byte[] fileBytes=File.ReadAllBytes(batchFile);//unused
                MemoryStream zipMemoryStream = new MemoryStream();
                ZipFile      tempZip         = new ZipFile();
                tempZip.AddFile(batchFile, "");
                tempZip.Save(zipMemoryStream);
                tempZip.Dispose();
                zipMemoryStream.Position = 0;
                byte[] zipFileBytes       = zipMemoryStream.GetBuffer();
                string zipFileBytesBase64 = Convert.ToBase64String(zipFileBytes);
                zipMemoryStream.Dispose();
                bool   isTest      = (clearinghouseClin.ISA15 == "T");
                string messageType = (isTest?"MCT":"MCD");              //medical
                if (medType == EnumClaimMedType.Institutional)
                {
                    messageType = (isTest?"HCT":"HCD");
                }
                else if (medType == EnumClaimMedType.Dental)
                {
                    //messageType=(isTest?"DCT":"DCD");//not used/tested yet, but planned for future.
                }
                EmdeonITS.ITSWS itsws = new EmdeonITS.ITSWS();
                itsws.Url = (isTest?emdeonITSUrlTest:emdeonITSUrl);
                EmdeonITS.ItsReturn response = itsws.PutFileExt(clearinghouseClin.LoginID, clearinghouseClin.Password, messageType, Path.GetFileName(batchFile), zipFileBytesBase64);
                if (response.ErrorCode != 0)                //Batch submission successful.
                {
                    throw new ODException("Emdeon rejected all claims in the current batch file " + batchFile + ". Error number from Emdeon: " + response.ErrorCode + ". Error message from Emdeon: " + response.Response);
                }
            }
            catch (Exception e) {
                ErrorMessage = e.Message;
                x837Controller.Rollback(clearinghouseClin, batchNum);
                return(false);
            }
            finally {
                try {
                    if (batchFile != "")
                    {
                        File.Delete(batchFile);
                    }
                }
                catch {
                    ErrorMessage = "Failed to remove batch file" + batchFile + ". Probably due to a permission issue.  Check folder permissions and manually delete.";
                }
            }
            return(true);
        }
Exemplo n.º 3
0
        ///<summary>Called from claimsend window and from Claim edit window.  Use 0 to get all waiting claims, or an actual claimnum to get just one claim.</summary>
        public static ClaimSendQueueItem[] GetQueueList(long claimNum, long clinicNum, long customTracking)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                return(Meth.GetObject <ClaimSendQueueItem[]>(MethodBase.GetCurrentMethod(), claimNum, clinicNum, customTracking));
            }
            string command =
                "SELECT claim.ClaimNum,carrier.NoSendElect"
                + ",CONCAT(CONCAT(CONCAT(concat(patient.LName,', '),patient.FName),' '),patient.MiddleI)"
                + ",claim.ClaimStatus,carrier.CarrierName,patient.PatNum,carrier.ElectID,MedType,claim.DateService,claim.ClinicNum "
                + "FROM claim "
                + "Left join insplan on claim.PlanNum = insplan.PlanNum "
                + "Left join carrier on insplan.CarrierNum = carrier.CarrierNum "
                + "Left join patient on patient.PatNum = claim.PatNum ";

            if (claimNum == 0)
            {
                command += "WHERE (claim.ClaimStatus = 'W' OR claim.ClaimStatus = 'P') ";
            }
            else
            {
                command += "WHERE claim.ClaimNum=" + POut.Long(claimNum) + " ";
            }
            if (clinicNum > 0)
            {
                command += "AND claim.ClinicNum=" + POut.Long(clinicNum) + " ";
            }
            if (customTracking > 0)
            {
                command += "AND claim.CustomTracking=" + POut.Long(customTracking) + " ";
            }
            command += "ORDER BY claim.DateService,patient.LName";
            DataTable table = Db.GetTable(command);

            ClaimSendQueueItem[] listQueue = new ClaimSendQueueItem[table.Rows.Count];
            for (int i = 0; i < table.Rows.Count; i++)
            {
                listQueue[i]             = new ClaimSendQueueItem();
                listQueue[i].ClaimNum    = PIn.Long(table.Rows[i][0].ToString());
                listQueue[i].NoSendElect = PIn.Bool(table.Rows[i][1].ToString());
                listQueue[i].PatName     = PIn.String(table.Rows[i][2].ToString());
                listQueue[i].ClaimStatus = PIn.String(table.Rows[i][3].ToString());
                listQueue[i].Carrier     = PIn.String(table.Rows[i][4].ToString());
                listQueue[i].PatNum      = PIn.Long(table.Rows[i][5].ToString());
                string           payorID = PIn.String(table.Rows[i]["ElectID"].ToString());
                EnumClaimMedType medType = (EnumClaimMedType)PIn.Int(table.Rows[i]["MedType"].ToString());
                listQueue[i].ClearinghouseNum = Clearinghouses.AutomateClearinghouseSelection(payorID, medType);
                listQueue[i].MedType          = medType;
                listQueue[i].DateService      = PIn.Date(table.Rows[i]["DateService"].ToString());
                listQueue[i].ClinicNum        = PIn.Long(table.Rows[i]["ClinicNum"].ToString());
            }
            return(listQueue);
        }
Exemplo n.º 4
0
        ///<summary>Returns the clearinghouseNum for claims for the supplied payorID.  If the payorID was not entered or if no default was set, then 0 is returned.</summary>
        public static long AutomateClearinghouseSelection(string payorID, EnumClaimMedType medType)
        {
            //No need to check RemotingRole; no call to db.
            //payorID can be blank.  For example, Renaissance does not require payorID.
            if (HList == null)
            {
                RefreshCache();
            }
            Clearinghouse clearinghouse = null;

            if (medType == EnumClaimMedType.Dental)
            {
                if (PrefC.GetLong(PrefName.ClearinghouseDefaultDent) == 0)
                {
                    return(0);
                }
                clearinghouse = GetClearinghouse(PrefC.GetLong(PrefName.ClearinghouseDefaultDent));
            }
            if (medType == EnumClaimMedType.Medical || medType == EnumClaimMedType.Institutional)
            {
                if (PrefC.GetLong(PrefName.ClearinghouseDefaultMed) == 0)
                {
                    return(0);
                }
                clearinghouse = GetClearinghouse(PrefC.GetLong(PrefName.ClearinghouseDefaultMed));
            }
            if (clearinghouse == null)          //we couldn't find a default clearinghouse for that medType.  Needs to always be a default.
            {
                return(0);
            }
            if (payorID != "" && HList.ContainsKey(payorID))          //an override exists for this payorID
            {
                Clearinghouse ch = GetClearinghouse((long)HList[payorID]);
                if (ch.Eformat == ElectronicClaimFormat.x837D_4010 || ch.Eformat == ElectronicClaimFormat.x837D_5010_dental)
                {
                    if (medType == EnumClaimMedType.Dental)                  //med type matches
                    {
                        return(ch.ClearinghouseNum);
                    }
                }
                if (ch.Eformat == ElectronicClaimFormat.x837_5010_med_inst)
                {
                    if (medType == EnumClaimMedType.Medical || medType == EnumClaimMedType.Institutional)                //med type matches
                    {
                        return(ch.ClearinghouseNum);
                    }
                }
            }
            //no override, so just return the default.
            return(clearinghouse.ClearinghouseNum);
        }
Exemplo n.º 5
0
        ///<summary>Returns the clearinghouseNum for claims for the supplied payorID.  If the payorID was not entered or if no default was set, then 0 is returned.</summary>
        public static long AutomateClearinghouseHqSelection(string payorID, EnumClaimMedType medType)
        {
            //No need to check RemotingRole; no call to db.
            //payorID can be blank.  For example, Renaissance does not require payorID.
            Clearinghouse clearinghouseHq = null;

            if (medType == EnumClaimMedType.Dental)
            {
                if (PrefC.GetLong(PrefName.ClearinghouseDefaultDent) == 0)
                {
                    return(0);
                }
                clearinghouseHq = GetClearinghouse(PrefC.GetLong(PrefName.ClearinghouseDefaultDent));
            }
            if (medType == EnumClaimMedType.Medical || medType == EnumClaimMedType.Institutional)
            {
                if (PrefC.GetLong(PrefName.ClearinghouseDefaultMed) == 0)
                {
                    return(0);
                }
                clearinghouseHq = GetClearinghouse(PrefC.GetLong(PrefName.ClearinghouseDefaultMed));
            }
            if (clearinghouseHq == null)          //we couldn't find a default clearinghouse for that medType.  Needs to always be a default.
            {
                return(0);
            }
            Clearinghouse clearingHouseOverride = GetClearinghouseByPayorID(payorID);

            if (clearingHouseOverride != null)           //an override exists for this payorID
            {
                if (clearingHouseOverride.Eformat == ElectronicClaimFormat.x837D_4010 || clearingHouseOverride.Eformat == ElectronicClaimFormat.x837D_5010_dental ||
                    clearingHouseOverride.Eformat == ElectronicClaimFormat.Canadian || clearingHouseOverride.Eformat == ElectronicClaimFormat.Ramq)
                {                                           //all dental formats
                    if (medType == EnumClaimMedType.Dental) //med type matches
                    {
                        return(clearingHouseOverride.ClearinghouseNum);
                    }
                }
                if (clearingHouseOverride.Eformat == ElectronicClaimFormat.x837_5010_med_inst)
                {
                    if (medType == EnumClaimMedType.Medical || medType == EnumClaimMedType.Institutional)                 //med type matches
                    {
                        return(clearingHouseOverride.ClearinghouseNum);
                    }
                }
            }
            //no override, so just return the default.
            return(clearinghouseHq.ClearinghouseNum);
        }
Exemplo n.º 6
0
 public static void GenerateMessageText(StreamWriter sw,Clearinghouse clearhouse,int batchNum,List<ClaimSendQueueItem> listQueueItems,EnumClaimMedType medType)
 {
     if(clearhouse.SeparatorData=="") {
         s="*";
     }
     else {
         s=""+Encoding.ASCII.GetChars(new byte[] { Convert.ToByte(clearhouse.SeparatorData,16) })[0]; //Validated to be a 2 digit hexadecimal number in UI.
     }
     if(clearhouse.ISA16=="") {
         isa16=":";
     }
     else {
         isa16=""+Encoding.ASCII.GetChars(new byte[] { Convert.ToByte(clearhouse.ISA16,16) })[0]; //Validated to be a 2 digit hexadecimal number in UI.
     }
     if(clearhouse.SeparatorSegment=="") {
         endSegment="~"+Environment.NewLine;
     }
     else {
         endSegment=""+Encoding.ASCII.GetChars(new byte[] { Convert.ToByte(clearhouse.SeparatorSegment,16) })[0]+Environment.NewLine; //Validated to be a 2 digit hexadecimal number in UI.
     }
     //Interchange Control Header (Interchange number tracked separately from transactionNum)
     //We set it to between 1 and 999 for simplicity
     sw.Write("ISA"+s
         +"00"+s//ISA01 2/2 Authorization Information Qualifier: 00=No Authorization Information Present (No meaningful information in ISA02).
         +Sout(clearhouse.ISA02,10,10)+s//ISA02 10/10 Authorization Information: Blank
         +"00"+s//ISA03 2/2 Security Information Qualifier: 00=No Security Information Present (No meaningful information in ISA04).
         +Sout(clearhouse.ISA04,10,10)+s//ISA04 10/10 Security Information: Blank
         +clearhouse.ISA05+s//ISA05 2/2 Interchange ID Qualifier: ZZ=mutually defined. 30=TIN. Validated
         +X12Generator.GetISA06(clearhouse)+s//ISA06 15/15 Interchange Sender ID: Sender ID(TIN) Or might be TIN of Open Dental.
         +clearhouse.ISA07+s//ISA07 2/2 Interchange ID Qualifier: ZZ=mutually defined. 30=TIN. Validated
         +Sout(clearhouse.ISA08,15,15)+s//ISA08 15/15 Interchange Receiver ID: Validated to make sure length is at least 2.
         +DateTime.Today.ToString("yyMMdd")+s//ISA09 6/6 Interchange Date: today's date.
         +DateTime.Now.ToString("HHmm")+s//ISA10 4/4 Interchange Time: current time
         +"^"+s//ISA11 1/1 Repetition Separator:
         +"00501"+s//ISA12 5/5 Interchange Control Version Number:
         +batchNum.ToString().PadLeft(9,'0')+s//ISA13 9/9 Interchange Control Number:
         +"0"+s//ISA14 1/1 Acknowledgement Requested: 0=No Interchange Acknowledgment Requested.
         +clearhouse.ISA15+s//ISA15 1/1 Interchange Usage Indicator: T=Test, P=Production. Validated.
         +isa16//ISA16 1/1 Component Element Separator:
         +endSegment);
     //Just one functional group.
     WriteFunctionalGroup(sw,listQueueItems,batchNum,clearhouse,medType);
     //Interchange Control Trailer
     sw.Write("IEA"+s
         +"1"+s//IEA01 1/5 Number of Included Functional Groups:
         +batchNum.ToString().PadLeft(9,'0')//IEA02 9/9 Interchange Control Number:
         +endSegment);
 }
Exemplo n.º 7
0
 ///<summary>Returns the clearinghouseNum for claims for the supplied payorID.  If the payorID was not entered or if no default was set, then 0 is returned.</summary>
 public static long AutomateClearinghouseSelection(string payorID,EnumClaimMedType medType)
 {
     //No need to check RemotingRole; no call to db.
     //payorID can be blank.  For example, Renaissance does not require payorID.
     if(HList==null) {
         RefreshCache();
     }
     Clearinghouse clearinghouse=null;
     if(medType==EnumClaimMedType.Dental){
         if(PrefC.GetLong(PrefName.ClearinghouseDefaultDent)==0){
             return 0;
         }
         clearinghouse=GetClearinghouse(PrefC.GetLong(PrefName.ClearinghouseDefaultDent));
     }
     if(medType==EnumClaimMedType.Medical || medType==EnumClaimMedType.Institutional){
         if(PrefC.GetLong(PrefName.ClearinghouseDefaultMed)==0){
             return 0;
         }
         clearinghouse=GetClearinghouse(PrefC.GetLong(PrefName.ClearinghouseDefaultMed));
     }
     if(clearinghouse==null){//we couldn't find a default clearinghouse for that medType.  Needs to always be a default.
         return 0;
     }
     if(payorID!="" && HList.ContainsKey(payorID)){//an override exists for this payorID
         Clearinghouse ch=GetClearinghouse((long)HList[payorID]);
         if(ch.Eformat==ElectronicClaimFormat.x837D_4010 || ch.Eformat==ElectronicClaimFormat.x837D_5010_dental){
             if(medType==EnumClaimMedType.Dental){//med type matches
                 return ch.ClearinghouseNum;
             }
         }
         if(ch.Eformat==ElectronicClaimFormat.x837_5010_med_inst){
             if(medType==EnumClaimMedType.Medical || medType==EnumClaimMedType.Institutional){//med type matches
                 return ch.ClearinghouseNum;
             }
         }
     }
     //no override, so just return the default.
     return clearinghouse.ClearinghouseNum;
 }
Exemplo n.º 8
0
        ///<summary>Supply a list of ClaimSendQueueItems.  Called from FormClaimSend.  Can only send to one clearinghouse at a time.
        ///The queueItems must contain at least one item.  Each item in queueItems must have the same ClinicNum.  Cannot include Canadian.</summary>
        public static void SendBatch(Clearinghouse clearinghouseClin, List <ClaimSendQueueItem> queueItems, EnumClaimMedType medType,
                                     IFormClaimFormItemEdit formClaimFormItemEdit, Renaissance.FillRenaissanceDelegate fillRenaissance, ITerminalConnector terminalConnector)
        {
            string messageText = "";

            if (clearinghouseClin.Eformat == ElectronicClaimFormat.Canadian)
            {
                MessageBox.Show(Lans.g("Eclaims", "Cannot send Canadian claims as part of Eclaims.SendBatch."));
                return;
            }
            //get next batch number for this clearinghouse
            int batchNum = Clearinghouses.GetNextBatchNumber(clearinghouseClin);

            //---------------------------------------------------------------------------------------
            //Create the claim file for this clearinghouse
            if (clearinghouseClin.Eformat == ElectronicClaimFormat.x837D_4010 ||
                clearinghouseClin.Eformat == ElectronicClaimFormat.x837D_5010_dental ||
                clearinghouseClin.Eformat == ElectronicClaimFormat.x837_5010_med_inst)
            {
                messageText = x837Controller.SendBatch(clearinghouseClin, queueItems, batchNum, medType, false);
            }
            else if (clearinghouseClin.Eformat == ElectronicClaimFormat.Renaissance)
            {
                messageText = Renaissance.SendBatch(clearinghouseClin, queueItems, batchNum, formClaimFormItemEdit, fillRenaissance);
            }
            else if (clearinghouseClin.Eformat == ElectronicClaimFormat.Dutch)
            {
                messageText = Dutch.SendBatch(clearinghouseClin, queueItems, batchNum);
            }
            else if (clearinghouseClin.Eformat == ElectronicClaimFormat.Ramq)
            {
                messageText = Ramq.SendBatch(clearinghouseClin, queueItems, batchNum);
            }
            else
            {
                messageText = "";      //(ElectronicClaimFormat.None does not get sent)
            }
            if (messageText == "")     //if failed to create claim file properly,
            {
                return;                //don't launch program or change claim status
            }
            //----------------------------------------------------------------------------------------
            //Launch Client Program for this clearinghouse if applicable
            if (clearinghouseClin.CommBridge == EclaimsCommBridge.None)
            {
                AttemptLaunch(clearinghouseClin, batchNum);
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.WebMD)
            {
                if (!WebMD.Launch(clearinghouseClin, batchNum))
                {
                    MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + WebMD.ErrorMessage);
                    return;
                }
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.BCBSGA)
            {
                if (!BCBSGA.Launch(clearinghouseClin, batchNum, terminalConnector))
                {
                    MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + BCBSGA.ErrorMessage);
                    return;
                }
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.Renaissance)
            {
                AttemptLaunch(clearinghouseClin, batchNum);
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.ClaimConnect)
            {
                if (ClaimConnect.Launch(clearinghouseClin, batchNum))
                {
                    MessageBox.Show("Upload successful.");
                }
                else
                {
                    MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + ClaimConnect.ErrorMessage);
                    return;
                }
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.RECS)
            {
                if (!RECS.Launch(clearinghouseClin, batchNum))
                {
                    MessageBox.Show(Lans.g("Eclaims", "Claim file created, but could not launch RECS client.") + "\r\n" + RECS.ErrorMessage);
                    //continue;
                }
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.Inmediata)
            {
                if (!Inmediata.Launch(clearinghouseClin, batchNum))
                {
                    MessageBox.Show(Lans.g("Eclaims", "Claim file created, but could not launch Inmediata client.") + "\r\n" + Inmediata.ErrorMessage);
                    //continue;
                }
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.AOS)           // added by SPK 7/13/05
            {
                if (!AOS.Launch(clearinghouseClin, batchNum))
                {
                    MessageBox.Show(Lans.g("Eclaims", "Claim file created, but could not launch AOS Communicator.") + "\r\n" + AOS.ErrorMessage);
                    //continue;
                }
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.PostnTrack)
            {
                AttemptLaunch(clearinghouseClin, batchNum);
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.MercuryDE)
            {
                if (!MercuryDE.Launch(clearinghouseClin, batchNum))
                {
                    MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + MercuryDE.ErrorMessage);
                    return;
                }
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.ClaimX)
            {
                if (!ClaimX.Launch(clearinghouseClin, batchNum))
                {
                    MessageBox.Show(Lans.g("Eclaims", "Claim file created, but encountered an error while launching ClaimX Client.") + ":\r\n" + ClaimX.ErrorMessage);
                }
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.EmdeonMedical)
            {
                if (!EmdeonMedical.Launch(clearinghouseClin, batchNum, medType))
                {
                    MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + EmdeonMedical.ErrorMessage);
                    return;
                }
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.DentiCal)
            {
                if (!DentiCal.Launch(clearinghouseClin, batchNum))
                {
                    MessageBox.Show(Lans.g("Eclaims", "Error sending.") + DentiCal.ErrorMessage);
                    return;
                }
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.NHS)
            {
                if (!NHS.Launch(clearinghouseClin, batchNum))
                {
                    MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + NHS.ErrorMessage);
                    return;
                }
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.EDS)
            {
                if (!EDS.Launch(clearinghouseClin, messageText))
                {
                    MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + EDS.ErrorMessage);
                    return;
                }
            }
            else if (clearinghouseClin.CommBridge == EclaimsCommBridge.Ramq)
            {
                if (!Ramq.Launch(clearinghouseClin, batchNum))
                {
                    MessageBox.Show(Lans.g("Eclaims", "Error sending.") + Ramq.ErrorMessage);
                    return;
                }
            }
            //----------------------------------------------------------------------------------------
            //finally, mark the claims sent. (only if not Canadian)
            EtransType etype = EtransType.ClaimSent;

            if (clearinghouseClin.Eformat == ElectronicClaimFormat.Renaissance)
            {
                etype = EtransType.Claim_Ren;
            }
            //Canadians cannot send in batches (see above).  RAMQ is performing a similar algorithm but the steps are in a different order in Ramq.cs.
            if (clearinghouseClin.Eformat != ElectronicClaimFormat.Canadian && clearinghouseClin.Eformat != ElectronicClaimFormat.Ramq)
            {
                //Create the etransmessagetext that all claims in the batch will point to.
                EtransMessageText etransMsgText = new EtransMessageText();
                etransMsgText.MessageText = messageText;
                EtransMessageTexts.Insert(etransMsgText);
                for (int j = 0; j < queueItems.Count; j++)
                {
                    Etrans etrans = Etranss.SetClaimSentOrPrinted(queueItems[j].ClaimNum, queueItems[j].PatNum,
                                                                  clearinghouseClin.HqClearinghouseNum, etype, batchNum, Security.CurUser.UserNum);
                    etrans.EtransMessageTextNum = etransMsgText.EtransMessageTextNum;
                    Etranss.Update(etrans);
                    //Now we need to update our cache of claims to reflect the change that took place in the database above in Etranss.SetClaimSentOrPrinted()
                    queueItems[j].ClaimStatus = "S";
                }
            }
        }
Exemplo n.º 9
0
		///<summary>Returns true if the communications were successful, and false if they failed. If they failed, a rollback will happen automatically by deleting the previously created X12 file. The batchnum is supplied for the possible rollback.  Also used for mail retrieval.</summary>
		public static bool Launch(Clearinghouse clearhouse,int batchNum,EnumClaimMedType medType){
			string batchFile="";
			try {
				if(!Directory.Exists(clearhouse.ExportPath)) {
					throw new Exception("Clearinghouse export path is invalid.");
				}
				//We make sure to only send the X12 batch file for the current batch, so that if there is a failure, then we know
				//for sure that we need to reverse the batch. This will also help us avoid any exterraneous/old batch files in the
				//same directory which might be left if there is a permission issue when trying to delete the batch files after processing.
				batchFile=Path.Combine(clearhouse.ExportPath,"claims"+batchNum+".txt");
				//byte[] fileBytes=File.ReadAllBytes(batchFile);//unused
				MemoryStream zipMemoryStream=new MemoryStream();
				ZipFile tempZip=new ZipFile();
				tempZip.AddFile(batchFile,"");
				tempZip.Save(zipMemoryStream);
				tempZip.Dispose();
				zipMemoryStream.Position=0;
				byte[] zipFileBytes=zipMemoryStream.GetBuffer();
				string zipFileBytesBase64=Convert.ToBase64String(zipFileBytes);
				zipMemoryStream.Dispose();
				if(clearhouse.ISA15=="P") {//production interface
					string messageType="MCD";//medical
					if(medType==EnumClaimMedType.Institutional) {
						messageType="HCD";
					}
					else if(medType==EnumClaimMedType.Dental) {
						//messageType="DCD";//not used/tested yet, but planned for future.
					}
					EmdeonITS.ITSWS itsws=new EmdeonITS.ITSWS();
					itsws.Url=emdeonITSUrl;
					EmdeonITS.ITSReturn response=itsws.PutFileExt(clearhouse.LoginID,clearhouse.Password,messageType,Path.GetFileName(batchFile),zipFileBytesBase64);
					if(response.ErrorCode!=0) { //Batch submission successful.
						throw new Exception("Emdeon rejected all claims in the current batch file "+batchFile+". Error number from Emdeon: "+response.ErrorCode+". Error message from Emdeon: "+response.Response);
					}
				}
				else {//test interface
					string messageType="MCT";//medical
					if(medType==EnumClaimMedType.Institutional) {
						messageType="HCT";
					}
					else if(medType==EnumClaimMedType.Dental) {
						//messageType="DCT";//not used/tested yet, but planned for future.
					}
					EmdeonITSTest.ITSWS itswsTest=new EmdeonITSTest.ITSWS();
					itswsTest.Url=emdeonITSUrlTest;
					EmdeonITSTest.ITSReturn responseTest=itswsTest.PutFileExt(clearhouse.LoginID,clearhouse.Password,messageType,Path.GetFileName(batchFile),zipFileBytesBase64);
					if(responseTest.ErrorCode!=0) { //Batch submission successful.
						throw new Exception("Emdeon rejected all claims in the current batch file "+batchFile+". Error number from Emdeon: "+responseTest.ErrorCode+". Error message from Emdeon: "+responseTest.Response);
					}
				}
			}
			catch(Exception e) {
				MessageBox.Show(e.Message);
				x837Controller.Rollback(clearhouse,batchNum);
				return false;
			}
			finally {
				try {
					if(batchFile!="") {
						File.Delete(batchFile);
					}
				}
				catch {
					MessageBox.Show("Failed to remove batch file "+batchFile+". Probably due to a permission issue. Check folder permissions and manually delete.");
				}
			}
			return true;
		}
Exemplo n.º 10
0
 ///<summary>Supply a list of ClaimSendQueueItems. Called from FormClaimSend.  Can only send to one clearinghouse at a time.  Able to send just send one claim.  Cannot include Canadian.</summary>
 public static void SendBatch(List<ClaimSendQueueItem> queueItems,Clearinghouse clearhouse,EnumClaimMedType medType)
 {
     string messageText="";
     if(clearhouse.Eformat==ElectronicClaimFormat.Canadian){
         MsgBox.Show("Eclaims","Cannot send Canadian claims as part of Eclaims.SendBatch.");
         return;
     }
     //get next batch number for this clearinghouse
     int batchNum=Clearinghouses.GetNextBatchNumber(clearhouse);
     //---------------------------------------------------------------------------------------
     //Create the claim file for this clearinghouse
     if(clearhouse.Eformat==ElectronicClaimFormat.x837D_4010
         || clearhouse.Eformat==ElectronicClaimFormat.x837D_5010_dental
         || clearhouse.Eformat==ElectronicClaimFormat.x837_5010_med_inst)
     {
         messageText=x837Controller.SendBatch(queueItems,batchNum,clearhouse,medType);
     }
     else if(clearhouse.Eformat==ElectronicClaimFormat.Renaissance){
         messageText=Renaissance.SendBatch(queueItems,batchNum);
     }
     else if(clearhouse.Eformat==ElectronicClaimFormat.Dutch) {
         messageText=Dutch.SendBatch(queueItems,batchNum);
     }
     else{
         messageText="";//(ElectronicClaimFormat.None does not get sent)
     }
     if(messageText==""){//if failed to create claim file properly,
         return;//don't launch program or change claim status
     }
     //----------------------------------------------------------------------------------------
     //Launch Client Program for this clearinghouse if applicable
     if(clearhouse.CommBridge==EclaimsCommBridge.None){
         AttemptLaunch(clearhouse,batchNum);
     }
     else if(clearhouse.CommBridge==EclaimsCommBridge.WebMD){
         if(!WebMD.Launch(clearhouse,batchNum)){
             MessageBox.Show(Lan.g("Eclaims","Error sending."));
             return;
         }
     }
     else if(clearhouse.CommBridge==EclaimsCommBridge.BCBSGA){
         if(!BCBSGA.Launch(clearhouse,batchNum)){
             MessageBox.Show(Lan.g("Eclaims","Error sending."));
             return;
         }
     }
     else if(clearhouse.CommBridge==EclaimsCommBridge.Renaissance){
         AttemptLaunch(clearhouse,batchNum);
     }
     else if(clearhouse.CommBridge==EclaimsCommBridge.ClaimConnect){
         if(!ClaimConnect.Launch(clearhouse,batchNum)){
             MessageBox.Show(Lan.g("Eclaims","Error sending."));
             return;
         }
     }
     else if(clearhouse.CommBridge==EclaimsCommBridge.RECS){
         if(!RECS.Launch(clearhouse,batchNum)){
             MessageBox.Show("Claim file created, but could not launch RECS client.");
             //continue;
         }
     }
     else if(clearhouse.CommBridge==EclaimsCommBridge.Inmediata){
         if(!Inmediata.Launch(clearhouse,batchNum)){
             MessageBox.Show("Claim file created, but could not launch Inmediata client.");
             //continue;
         }
     }
     else if(clearhouse.CommBridge==EclaimsCommBridge.AOS){ // added by SPK 7/13/05
         if(!AOS.Launch(clearhouse,batchNum)){
             MessageBox.Show("Claim file created, but could not launch AOS Communicator.");
             //continue;
         }
     }
     else if(clearhouse.CommBridge==EclaimsCommBridge.PostnTrack){
         AttemptLaunch(clearhouse,batchNum);
     }
     else if(clearhouse.CommBridge==EclaimsCommBridge.MercuryDE){
         if(!MercuryDE.Launch(clearhouse,batchNum)){
             MsgBox.Show("Eclaims","Error sending.");
             return;
         }
     }
     else if(clearhouse.CommBridge==EclaimsCommBridge.ClaimX) {
         if(!ClaimX.Launch(clearhouse,batchNum)) {
             MessageBox.Show("Claim file created, but encountered an error while launching ClaimX Client.");
         }
     }
     else if(clearhouse.CommBridge==EclaimsCommBridge.EmdeonMedical) {
         if(!EmdeonMedical.Launch(clearhouse,batchNum,medType)) {
             MessageBox.Show(Lan.g("Eclaims","Error sending."));
             return;
         }
     }
     //----------------------------------------------------------------------------------------
     //finally, mark the claims sent. (only if not Canadian)
     EtransType etype=EtransType.ClaimSent;
     if(clearhouse.Eformat==ElectronicClaimFormat.Renaissance){
         etype=EtransType.Claim_Ren;
     }
     if(clearhouse.Eformat!=ElectronicClaimFormat.Canadian){
         for(int j=0;j<queueItems.Count;j++){
             Etrans etrans=Etranss.SetClaimSentOrPrinted(queueItems[j].ClaimNum,queueItems[j].PatNum,clearhouse.ClearinghouseNum,etype,batchNum);
             Etranss.SetMessage(etrans.EtransNum,messageText);
         }
     }
 }
Exemplo n.º 11
0
        ///<summary>Called from Eclaims and includes multiple claims.  Returns the string that was sent.
        ///The string needs to be parsed to determine the transaction numbers used for each claim.</summary>
        public static string SendBatch(Clearinghouse clearinghouseClin, List <ClaimSendQueueItem> queueItems, int batchNum, EnumClaimMedType medType,
                                       bool isAutomatic)
        {
            //each batch is already guaranteed to be specific to one clearinghouse, one clinic, and one EnumClaimMedType
            //Clearinghouse clearhouse=ClearinghouseL.GetClearinghouse(queueItems[0].ClearinghouseNum);
            string saveFile = GetFileName(clearinghouseClin, batchNum, isAutomatic);

            if (saveFile == "")
            {
                return("");
            }
            string messageText = "";

            using (MemoryStream ms = new MemoryStream()) {
                using (StreamWriter sw = new StreamWriter(ms)) {
                    if (clearinghouseClin.Eformat == ElectronicClaimFormat.x837D_4010)
                    {
                        X837_4010.GenerateMessageText(sw, clearinghouseClin, batchNum, queueItems);
                    }
                    else                      //Any of the 3 kinds of 5010
                    {
                        X837_5010.GenerateMessageText(sw, clearinghouseClin, batchNum, queueItems, medType);
                    }
                    sw.Flush();                    //Write contents of sw into ms.
                    ms.Position = 0;               //Reset position to 0, or else the StreamReader below will not read anything.
                    using (StreamReader sr = new StreamReader(ms, Encoding.ASCII)) {
                        messageText = sr.ReadToEnd();
                    }
                }
            }
            if (clearinghouseClin.IsClaimExportAllowed)
            {
                if (clearinghouseClin.CommBridge == EclaimsCommBridge.PostnTrack)
                {
                    //need to clear out all CRLF from entire file
                    messageText = messageText.Replace("\r", "");
                    messageText = messageText.Replace("\n", "");
                }
                File.WriteAllText(saveFile, messageText, Encoding.ASCII);
                CopyToArchive(saveFile);
            }
            return(messageText);
        }
Exemplo n.º 12
0
		private static void WriteFunctionalGroup(StreamWriter sw,List<ClaimSendQueueItem> queueItems,int batchNum,Clearinghouse clearhouse,EnumClaimMedType medType) {
			#region Functional Group Header
			int transactionNum=1;//Gets incremented for each carrier. Can be reused in other functional groups and interchanges, so not persisted
			//Functional Group Header
			string groupControlNumber=batchNum.ToString();//Must be unique within file.  We will use batchNum
			string industryIdentifierCode="";
			if(medType==EnumClaimMedType.Medical) {
				industryIdentifierCode="005010X222A1";
			}
			else if(medType==EnumClaimMedType.Institutional) {
				industryIdentifierCode="005010X223A2";
			}
			else if(medType==EnumClaimMedType.Dental) {
				industryIdentifierCode="005010X224A2";
			}
			sw.Write("GS"+s
				+"HC"+s//GS01 2/2 Functional Identifier Code: Health Care Claim.
				+X12Generator.GetGS02(clearhouse)+s//GS02 2/15 Application Sender's Code: Sometimes Jordan Sparks.  Sometimes the sending clinic.
				+Sout(clearhouse.GS03,15,2)+s//GS03 2/15 Application Receiver's Code:
				+DateTime.Today.ToString("yyyyMMdd")+s//GS04 8/8 Date: today's date.
				+DateTime.Now.ToString("HHmm")+s//GS05 4/8 TIME: current time.
				+groupControlNumber+s//GS06 1/9 Group Control Number: No padding necessary.
				+"X"+s//GS07 1/2 Responsible Agency Code: X=Accredited Standards Committee X12.
				+industryIdentifierCode//GS08 1/12 Version/Release/Industry Identifier Code:
				+endSegment);
			#endregion Functional Group Header
			#region Define Variables
			int HLcount=1;
			int parentProv=0;//the HL sequence # of the current provider.
			int parentSubsc=0;//the HL sequence # of the current subscriber.
			string hasSubord="";//0 if no subordinate, 1 if at least one subordinate
			Claim claim;
			InsPlan insPlan;
			InsPlan otherPlan=null;
			InsSub sub;
			InsSub otherSub=new InsSub();
			Patient patient;
			Patient subscriber;
			Patient otherSubsc=new Patient();
			Carrier carrier;
			Carrier otherCarrier=new Carrier();
			List<ClaimProc> claimProcList;//all claimProcs for a patient.
			List<ClaimProc> claimProcs;
			List<Procedure> procList;
			List<ToothInitial> initialList;
			List<PatPlan> patPlans;
			Procedure proc;
			ProcedureCode procCode;
			Provider provTreat;//claim level treating provider.
			Provider billProv=null;
			Clinic clinic=null;
			seg=0;
			#endregion Define Variables
			#region Transaction Set Header
			//if(i==0//if this is the first claim
			//	|| claimItems[i].PayorId0 != claimItems[i-1].PayorId0)//or the payorID has changed
			//{
			//	newTrans=true;
			//	seg=0;
			//}
			//else newTrans=false;
			//if(newTrans) {
			//Transaction Set Header (one for each carrier)
			//transactionNum gets incremented in SE section
			//ST02 Transact. control #. Must be unique within ISA
			//NO: So we used combination of transaction and group, eg 00011
			sw.Write("ST"+s
				+"837"+s//ST01 3/3 Transaction Set Identifier Code: 
				+transactionNum.ToString().PadLeft(4,'0')+s//ST02 4/9 Transaction Set Control Number: 
				+industryIdentifierCode);//ST03 1/35 Implementation Convention Reference:
			EndSegment(sw);
			sw.Write("BHT"+s
				+"0019"+s//BHT01 4/4 Hierarchical Structure Code: 0019=Information Source, Subscriber, Dependant.
				+"00"+s//BHT02 2/2 Transaction Set Purpose Code: 00=Original transmissions are transmissions which have never been sent to the reciever.
				+transactionNum.ToString().PadLeft(4,'0')+s//BHT03 1/50 Reference Identification: Can be same as ST02.
				+DateTime.Now.ToString("yyyyMMdd")+s//BHT04 8/8 Date: 
				+DateTime.Now.ToString("HHmmss")+s//BHT05 4/8 Time: 
				+"CH");//BHT06 2/2 Transaction Type Code: CH=Chargable.
			EndSegment(sw);
			//1000A Submitter is OPEN DENTAL and sometimes it's the practice
			//(depends on clearinghouse and Partnership agreements)
			//See 2010AA PER (after REF) for the new billing provider contact phone number
			//1000A NM1: 41 (medical,institutional,dental) Submitter Name.
			Write1000A_NM1(sw,clearhouse);
			//1000A PER: IC (medical,institutional,dental) Submitter EDI Contact Information. Contact number.
			Write1000A_PER(sw,clearhouse);
			//1000B NM1: 40 (medical,institutional,dental) Receiver Name. Always the Clearinghouse.
			sw.Write("NM1"+s
				+"40"+s//NM101 2/3 Entity Identifier Code: 40=Receiver.
				+"2"+s);//NM102 1/1 Entity Type Qualifier: 2=Non-Person Entity.
			if(IsClaimConnect(clearhouse)) {
				sw.Write("CLAIMCONNECT"+s);//NM103 1/60 Name Last or Organization Name: Receiver Name.
			}
			else if(IsDentiCal(clearhouse)) {
				sw.Write("DENTICAL"+s);//NM103 1/60 Name Last or Organization Name: Receiver Name.
			}
			else {
				sw.Write(Sout(clearhouse.Description,60)+s);//NM103 1/60 Name Last or Organization Name: Receiver Name.
			}
			sw.Write(s//NM104 1/35 Name First: Not Used.
				+s//NM105 1/25 Name Middle: Not Used.
				+s//NM106 1/10 Name Prefix: Not Used.
				+s//NM107 1/10 Name Suffix: Not Used.
				+"46"+s);//NM108 1/2 Identification Code Qualifier: 46=Electronic Transmitter Identification Number (ETIN).
			if(IsDentiCal(clearhouse)) {
				sw.Write("1941461312");//NM109 2/80 Identification Code: Receiver ID Code. aka ETIN#.
			}
			else {
				sw.Write(Sout(clearhouse.ISA08,80,2));//NM109 2/80 Identification Code: Receiver ID Code. aka ETIN#.
			}
			EndSegment(sw);//NM110 through NM112 are not used.
			HLcount=1;
			parentProv=0;//the HL sequence # of the current provider.
			parentSubsc=0;//the HL sequence # of the current subscriber.
			hasSubord="";//0 if no subordinate, 1 if at least one subordinate
			//}
			#endregion
			for(int i=0;i<queueItems.Count;i++) {
				#region Initialize Variables
				claim=Claims.GetClaim(queueItems[i].ClaimNum);
				insPlan=InsPlans.GetPlan(claim.PlanNum,new List<InsPlan>());
				sub=InsSubs.GetSub(claim.InsSubNum,null);
				//insPlan could be null if db corruption. No error checking for that
				otherPlan=null;//Must be reset each time through because if otherPlan!=null below then we assume the current claim has a secondary plan.
				if(claim.PlanNum2>0) {
					otherPlan=InsPlans.GetPlan(claim.PlanNum2,new List<InsPlan>());
					otherSub=InsSubs.GetSub(claim.InsSubNum2,null);
					otherSubsc=Patients.GetPat(otherSub.Subscriber);
					otherCarrier=Carriers.GetCarrier(otherPlan.CarrierNum);
				}
				patient=Patients.GetPat(claim.PatNum);
				subscriber=Patients.GetPat(sub.Subscriber);
				carrier=Carriers.GetCarrier(insPlan.CarrierNum);
				claimProcList=ClaimProcs.Refresh(patient.PatNum);
				claimProcs=ClaimProcs.GetForSendClaim(claimProcList,claim.ClaimNum);
				procList=Procedures.Refresh(claim.PatNum);
				initialList=ToothInitials.Refresh(claim.PatNum);
				patPlans=PatPlans.Refresh(patient.PatNum);
				#endregion Initialize Variables
				#region Billing Provider
				//Billing address is based on clinic, not provider.  All claims in a batch are guaranteed to be from a single clinic.  That validation is done in FormClaimSend.
				//Although, now that we have a separate loop for each claim, we might be able to allow a batch with mixed clinics.
				if(!PrefC.GetBool(PrefName.EasyNoClinics)) {//if using clinics
					clinic=Clinics.GetClinic(claim.ClinicNum);//might be null
				}
				//2000A HL: (medical,instituational,dental) Billing Provider Hierarchical Level.
				sw.Write("HL"+s+HLcount.ToString()+s//HL01 1/12 Heirarchical ID Number: 
					+s//HL02 1/12 Hierarchical Parent ID Number: Not used.
					+"20"+s//HL03 1/2 Heirarchical Level Code: 20=Information Source.
					+"1");//HL04 1/1 Heirarchical Child Code. 1=Additional Subordinate HL Data Segment in This Hierarchical Structure.
				EndSegment(sw);
				//billProv=ProviderC.ListLong[Providers.GetIndexLong(claimItems[i].ProvBill1)];
				billProv=Providers.GetProv(claim.ProvBill);
				//2000A PRV: BI (medical,institutional,dental) Billing Provider Specialty Information. Situational. Required when billing provider is treating provider.
				bool usePrvBilling=false;
				if(claim.ProvBill==claim.ProvTreat) {
					usePrvBilling=true;
				}
				if(IsWashingtonMedicaid(clearhouse,carrier)) {
					usePrvBilling=true;
				}
				if(usePrvBilling) {
					sw.Write("PRV"+s
						+"BI"+s//PRV01 1/3 Provider Code: BI=Billing.
						+"PXC"+s//PRV02 2/3 Reference Identification Qualifier: PXC=Health Care Provider Taxonomy Code.
						+X12Generator.GetTaxonomy(billProv));//PRV03 1/50 Reference Identification: Provider Taxonomy Code.
					EndSegment(sw);//PRV04 through PRV06 are not used.
				}
				//2000A CUR: (medical,instituational,dental) Foreign Currency Information. Situational. We do not need to specify because united states dollars are default.
				//2010AA NM1: 85 (medical,institutional,dental) Billing Provider Name.
				if(medType==EnumClaimMedType.Institutional) {
					billProv.IsNotPerson=true;//Required by X12 specification. Cannot send a person as the billing provider.
				}
				WriteNM1Provider("85",sw,billProv);
				//2010AA N3: (medical,institutional,dental) Billing Provider Address.
				string billingAddress1="";
				string billingAddress2="";
				string billingCity="";
				string billingState="";
				string billingZip="";
				if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) {
					billingAddress1=PrefC.GetString(PrefName.PracticeBillingAddress);
					billingAddress2=PrefC.GetString(PrefName.PracticeBillingAddress2);
					billingCity=PrefC.GetString(PrefName.PracticeBillingCity);
					billingState=PrefC.GetString(PrefName.PracticeBillingST);
					billingZip=PrefC.GetString(PrefName.PracticeBillingZip);
				}
				else if(clinic==null) {
					billingAddress1=PrefC.GetString(PrefName.PracticeAddress);
					billingAddress2=PrefC.GetString(PrefName.PracticeAddress2);
					billingCity=PrefC.GetString(PrefName.PracticeCity);
					billingState=PrefC.GetString(PrefName.PracticeST);
					billingZip=PrefC.GetString(PrefName.PracticeZip);
				}
				else {
					billingAddress1=clinic.Address;
					billingAddress2=clinic.Address2;
					billingCity=clinic.City;
					billingState=clinic.State;
					billingZip=clinic.Zip;
				}
				sw.Write("N3"+s+Sout(billingAddress1,55));//N301 1/55 Address Information:
				if(billingAddress2!="") {
					sw.Write(s+Sout(billingAddress2,55));//N302 1/55 Address Information:
				}
				EndSegment(sw);
				//2010AA N4: (medical,institutional,dental) Billing Provider City, State, Zip Code.
				sw.Write("N4"+s+Sout(billingCity,30)+s//N401 2/30 City Name: 
					+Sout(billingState,2,2)+s//N402 2/2 State or Province Code: 
					+Sout(billingZip.Replace("-",""),15));//N403 3/15 Postal Code: 
				EndSegment(sw);//NM404 through NM407 are either situational with United States as default, or not used, so we don't specify any of them.
				//2010AA REF: EI (medical,institutional,dental) Billing Provider Tax Identification.
				sw.Write("REF"+s);
				if(medType==EnumClaimMedType.Medical) {
					sw.Write((billProv.UsingTIN?"EI":"SY")+s);//REF01 2/3 Reference Identification Qualifier: EI=Employer's Identification Number (EIN). SY=Social Security Number (SSN).
				}
				else if(medType==EnumClaimMedType.Institutional) {
					sw.Write("EI"+s);//REF01 2/3 Reference Identification Qualifier: EI=Employer's Identification Number (EIN).
				}
				else if(medType==EnumClaimMedType.Dental) {
					sw.Write((billProv.UsingTIN?"EI":"SY")+s);//REF01 2/3 Reference Identification Qualifier: EI=Employer's Identification Number (EIN). SY=Social Security Number (SSN).
				}
				sw.Write(Sout(billProv.SSN,50));//REF02 1/50 Reference Identification. Tax ID #.
				EndSegment(sw);//REF03 and REF04 are not used.
				if(medType==EnumClaimMedType.Medical || medType==EnumClaimMedType.Dental) {
					//2010AA REF: (medical,dental) Billing Provider UIPN/License Information: Situational. We do not use. Max repeat 2.
				}
				if(medType==EnumClaimMedType.Dental) {
					//2010AA REF: (dental) State License Number: Required by RECS and Emdeon clearinghouses. We do NOT validate that it's entered because sending it with non-persons causes problems.
					//if(IsEmdeonDental(clearhouse) || clearhouse.CommBridge==EclaimsCommBridge.RECS) {
					if(!IsDentiCal(clearhouse)) { //Denti-Cal never wants this.
						if(billProv.StateLicense!="") {
							sw.Write("REF"+s
								+"0B"+s//REF01 2/3 Reference Identification Qualifier: 0B=State License Number.
								+Sout(billProv.StateLicense,50));//REF02 1/50 Reference Identification: 
							EndSegment(sw);//REF03 and REF04 are not used.
						}
					}
					//2010AA REF G5 (dental) Site Identification Number: NOT IN X12 5010 STANDARD DOCUMENTATION. Only required by Emdeon.
					if(IsEmdeonDental(clearhouse)) {
						Write2010AASiteIDforEmdeon(sw,billProv,carrier.ElectID);
					}
				}
				//2010AA PER: IC (medical,institutional,dental) Billing Provider Contact Information: Probably required by a number of carriers and by Emdeon.
				sw.Write("PER"+s
					+"IC"+s//PER01 2/2 Contact Function Code: IC=Information Contact.
					+Sout(PrefC.GetString(PrefName.PracticeTitle),60)+s//PER02 1/60 Name: Practice Title.
					+"TE"+s);//PER03 2/2 Communication Number Qualifier: TE=Telephone.
				if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) {
					sw.Write(Sout(PrefC.GetString(PrefName.PracticePhone),256));//PER04  1/256 Communication Number: Telephone number.
				}
				else if(clinic==null){
					sw.Write(Sout(PrefC.GetString(PrefName.PracticePhone),256));//PER04  1/256 Communication Number: Telephone number.
				}
				else{
					sw.Write(Sout(clinic.Phone,256));//PER04  1/256 Communication Number: Telephone number.
				}
				EndSegment(sw);//PER05 through PER08 are situational and PER09 is not used. We do not use.
				if(PrefC.GetString(PrefName.PracticePayToAddress)!="") {
					//2010AB NM1: 87 (medical,institutional,dental) Pay-To Address Name.
					sw.Write("NM1"+
						s+"87"+s);//NM101 2/3 Entity Identifier Code: 87=Pay-to Provider.
					if(medType==EnumClaimMedType.Institutional) {
						sw.Write("2");//NM102 1/1 Entity Type Qualifier: 2=Non-Person Entity.
					}
					else { //(medical,dental)
						sw.Write((billProv.IsNotPerson?"2":"1"));//NM102 1/1 Entity Type Qualifier: 1=Person, 2=Non-Person Entity.
					}
					EndSegment(sw);//NM103 through NM112 are not used.
					//2010AB N3: (medical,institutional,dental) Pay-To Address.
					sw.Write("N3"+s+Sout(PrefC.GetString(PrefName.PracticePayToAddress),55));//N301 1/55 Address Information:
					if(PrefC.GetString(PrefName.PracticePayToAddress2)!="") {
						sw.Write(s+Sout(PrefC.GetString(PrefName.PracticePayToAddress2),55));//N302 1/55 Address Information:
					}
					EndSegment(sw);
					//2010AB N4: (medical,institutional,dental) Pay-To Address City, State, Zip Code.
					sw.Write("N4"+s+Sout(PrefC.GetString(PrefName.PracticePayToCity),30)+s//N401 2/30 City Name: 
						+Sout(PrefC.GetString(PrefName.PracticePayToST),2,2)+s//N402 2/2 State or Province Code: 
						+Sout(PrefC.GetString(PrefName.PracticePayToZip).Replace("-",""),15));//N403 3/15 Postal Code: 
					EndSegment(sw);//NM404 through NM407 are either situational with United States as default, or not used, so we don't specify any of them.
				}
				//2010AC NM1: 98 (medical,institutional,dental) Pay-To Plan Name. We do not use.
				//2010AC N3: (medical,institutional,dental) Pay-To Plan Address. We do not use.
				//2010AC N4: (medical,institutional,dental) Pay-To Plan City, State, Zip Code. We do not use.
				//2010AC REF: (medical,institutional,dental) Pay-To Plan Secondary Identification. We do not use.
				//2010AC REF: (medical,institutional,dental) Pay-To Plan Tax Identification Number. We do not use.
				parentProv=HLcount;
				HLcount++;
				#endregion Billing Provider
				#region Attachments
				/*if(IsTesia(clearhouse) && claim.Attachments.Count>0){//If Tesia and has attachments
					claim.ClaimNote="TESIA#"+claim.ClaimNum.ToString()+" "+claim.ClaimNote;
					string saveFolder=clearhouse.ExportPath;//we've already tested to make sure this exists.
					string saveFile;
					string storedFile;
					for(int c=0;c<claim.Attachments.Count;c++){
						saveFile=ODFileUtils.CombinePaths(saveFolder,
							claim.ClaimNum.ToString()+"_"+(c+1).ToString()+Path.GetExtension(claim.Attachments[c].DisplayedFileName)+".IMG");
						storedFile=ODFileUtils.CombinePaths(FormEmailMessageEdit.GetAttachPath(),claim.Attachments[c].ActualFileName);
						File.Clone(storedFile,saveFile,true);
					}					
				}*/
				#endregion
				#region Subscriber
				if(patient.PatNum==subscriber.PatNum){//if patient is the subscriber
					hasSubord="0";//-claim level will follow
					//subordinate patients will not follow in this loop.  The subscriber loop will be duplicated for them.
				}
				else {//patient is not the subscriber
					hasSubord="1";//-patient will always follow
				}
				//2000B HL: (medical,institutional,dental) Subscriber Hierarchical Level.
				sw.Write("HL"+s+HLcount.ToString()+s//HL01 1/12 Hierarchical ID Number:
					+parentProv.ToString()+s//HL02 1/12 Hierarchical Parent ID Number: parent HL is always the billing provider HL.
					+"22"+s//HL03 1/2 Hierarchical Level Code: 22=Subscriber.
					+hasSubord);//HL04 1/1 Hierarchical Child Code: 0=No subordinate HL segment in this hierarchical structure. 1=Additional subordinate HL data segment in this hierarchical structure.
				EndSegment(sw);
				//2000B SBR: (medical,institutional,dental) Subscriber Information.
				sw.Write("SBR"+s);
				bool claimIsPrimary=true;//we currently support only primary and secondary.  Plan2, if present, must be the opposite.
				if(claim.ClaimType=="PreAuth") {
					if(otherPlan!=null && PatPlans.GetOrdinal(claim.InsSubNum2,patPlans) < PatPlans.GetOrdinal(claim.InsSubNum,patPlans)) { //When there are two plans and the secondary plan is in the primary ins position.
						claimIsPrimary=false;
					}
				}
				else if(otherPlan!=null && (otherPlan.IsMedical || insPlan.IsMedical)) { //When there are two plans and at least one plan is medical.
					if(PatPlans.GetOrdinal(claim.InsSubNum2,patPlans) < PatPlans.GetOrdinal(claim.InsSubNum,patPlans)) { //The insurance plan order is determined by patplan.ordinal
						claimIsPrimary=false;
					}
				}
				else if(claim.ClaimType=="P") {
				}
				else if(claim.ClaimType=="S") { //Verification ensures that there are two plans associated with the claim in this case.
					claimIsPrimary=false;
				}
				else if(claim.ClaimType=="Other") { //Also used for a medical claim with only one insurance.
					//We always send medical plans as primary.  They are totally separate from the ordinals for dental.
				}
				else if(claim.ClaimType=="Cap") {
					//All captication claims are treated as primary claims.
					//todo: is secondary capitation possible?
				}
				sw.Write((claimIsPrimary?"P":"S")+s);//SBR01 1/1 Payer Responsibility Sequence Number Code: 
				string relationshipCode="";//empty if patient is not subscriber.
				if(patient.PatNum==subscriber.PatNum) {//if patient is the subscriber
					relationshipCode="18";
				}
				sw.Write(relationshipCode+s//SBR02 2/2 Individual Relationship Code: 18=Self (The only option besides blank).
					+Sout(insPlan.GroupNum,50)+s);//SBR03 1/50 Reference Identification: Does not need to be validated because group number is optional.
				//SBR04 1/60 Name: Situational. Required when SBR03 is not used. Does not need to be validated because group name is optional.
				if(insPlan.GroupNum!="") {
					sw.Write(s);
				} 
				else {
					sw.Write(Sout(insPlan.GroupName,60)+s);
				}
				sw.Write(s//SBR05 1/3 Insurance Type Code. Situational.  Skip because we don't support secondary Medicare.
					+s//SBR06 1/1 Coordination of Benefits Code: Not used.
					+s//SBR07 1/1 Yes/No Condition or Respose Code: Not used.
					+s//SBR08 2/2 Employment Status Code: Not used.
					+GetFilingCode(insPlan));//SBR09: 12=PPO,17=DMO,BL=BCBS,CI=CommercialIns,FI=FEP,HM=HMO. Will no longer be required when HIPPA National Plan ID is mandated.
				EndSegment(sw);
				if(medType==EnumClaimMedType.Medical) {
					//2000B PAT: (medical) Patient Information. Situational. Required when the patient is the subscriber or considered to be the subscriber and at least one of the element requirements are met. Element requirements include: when the patient is deceased and the date of death is available; or when the claim involves Medicare Durable Medical Equipment Regional Carriers Certificate of Medical Necessity (DMERC CMN) 02.03, 10.02, or DMA MAC 10.03; or when law requires to know if the patient is pregnant or not. We do not use, because we do not track death date, durable medical equipment information, nor do we know weather or not the patient is pregnant. Some of these fields may be necessary in the future, but not likely since our medical claims are usually pretty simple.
				}
				//2010BA NM1: IL (medical,institutional,dental) Subscriber Name.
				sw.Write("NM1"+s
					+"IL"+s//NM101 2/3 Entity Identifier Code: IL=Insured or Subscriber.
					+"1"+s//NM102 1/1 Entity Type Qualifier: 1=Person, 2=Non-Person Entity.
					+Sout(subscriber.LName,60)+s//NM103 1/60 Name Last or Organization Name: Never blank, because validated in the patient edit window when a patient is added/edited.
					+Sout(subscriber.FName,35)+s//NM104 1/35 Name First:
					+Sout(subscriber.MiddleI,25)+s//NM105 1/25 Name Middle:
					+s//NM106 1/10 Name Prefix: Not Used.
					+s//NM107 1/10 Name Suffix: Situational. Not present in Open Dental yet so we leave blank.
					+"MI"+s//NM108 1/2 Identification Code Qualifier: MI=Member Identification Number.
					+Sout(sub.SubscriberID.Replace("-",""),80,2));//NM109 2/80 Identification Code: Situational. Required when NM102=1.
				EndSegment(sw);//NM110 through NM112 are not used.
				//In 4010s, at the request of Emdeon, we always include N3,N4,and DMG even if patient is not subscriber.  This did not make the transaction non-compliant, and they found it useful.
				//In 5010s, we will follow the X12 specification for most clearinghouses and only include subsc address when subscriber=patient.
				//But for any clearinghouse who requests it, we will always include, [js 3/14/13 even when subscriber!=patient].  List them here:
				//ClaimConnect, EmdeonMed, EmdeonDent, LindsayTechnicalConsultants, OfficeAlly: Always include.
				//PostNTrack, BCBSIdaho: Only include when subscriber=patient.
				bool subscIncludeAddressAndGender=false;
				if(IsClaimConnect(clearhouse) || IsEmdeonDental(clearhouse) || IsEmdeonMedical(clearhouse) || IsLindsayTechnicalConsultants(clearhouse) || IsOfficeAlly(clearhouse)) {
					subscIncludeAddressAndGender=true;
				}
				else {//X12 standard behavior for everyone else, including: BCBSIdaho, ColoradoMedicaid, Denti-Cal, PostNTrack, WashingtonMedicaid.
					if(subscriber.PatNum==patient.PatNum) {//[js 3/14/13 only include when subscriber==patient]
						subscIncludeAddressAndGender=true;
					}
					//[js 3/14/13 when subscriber!=patient, don't include address]
				}
				if(subscIncludeAddressAndGender) {
					//2010BA N3: (medical,institutional,dental) Subscriber Address. Situational. Required when the patient is the subscriber.
					sw.Write("N3"+s+Sout(subscriber.Address,55));//N301 1/55 Address Information:
					if(subscriber.Address2!="") {
						sw.Write(s+Sout(subscriber.Address2,55));//N302 1/55 Address Information:
					}
					EndSegment(sw);
					//2010BA N4: (medical,institutional,dental) Subscriber City, State, Zip Code. Situational. Required when the patient is the subscriber.
					sw.Write("N4"+s
						+Sout(subscriber.City,30)+s//N401 2/30 City Name:
						+Sout(subscriber.State,2,2)+s//N402 2/2 State or Provice Code:
						+Sout(subscriber.Zip.Replace("-",""),15));//N403 3/15 Postal Code:
					EndSegment(sw);//N404 through N407 either not used or required for addresses outside of the United States.
					//2010BA DMG: (medical,institutional,dental) Subscriber Demographic Information. Situational. Required when the patient is the subscriber.
					//Carriers tend to complain if the BD is missing for the subscriber even though it's not strictly required.  So we will require it from users.
					sw.Write("DMG"+s
						+"D8"+s//DMG01 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD.
						+subscriber.Birthdate.ToString("yyyyMMdd")+s//DMG02 1/35 Date Time Period: Birthdate. The subscriber birtdate is validated.
						+GetGender(subscriber.Gender));//DMG03 1/1 Gender Code: F=Female, M=Male, U=Unknown.
					EndSegment(sw);
				}
				//2010BA REF: SY (medical,institutional,dental) Secondary Secondary Identification: Situational. Required when an additional identification number to that provided in NM109 of this loop is necessary. We do not use this.
				//2010BA REF: Y4 (medical,institutional,dental) Property and Casualty Claim Number: Required when the services included in this claim are to be considered as part of a property and casualty claim. We do not use this.
				//2010BA PER: IC (medical) Property and Casualty Subscriber Contact information: Situational. We do not use this.
				//2010BB NM1: PR (medical,institutional,dental) Payer Name.
				sw.Write("NM1"+s
					+"PR"+s//NM101 2/3 Entity Identifier Code: PR=Payer.
					+"2"+s);//NM102 1/1 Entity Type Qualifier: 2=Non-Person Entity.
				//NM103 1/60 Name Last or Organization Name:
				if(IsEMS(clearhouse)) {
					//This is a special situation requested by EMS.  This tacks the employer onto the end of the carrier.
					sw.Write(Sout(carrier.CarrierName,30)+"|"+Sout(Employers.GetName(insPlan.EmployerNum),30)+s);
				}
				else if(IsDentiCal(clearhouse)) {
					sw.Write("DENTICAL"+s);
				}
				else {
					sw.Write(Sout(carrier.CarrierName,60)+s);
				}
				sw.Write(s//NM104 1/35 Name First: Not used.
					+s//NM105 1/25 Name Middle: Not used.
					+s//NM106 1/10 Name Prefix: Not used.
					+s//NM107 1/10 Name Suffix: Not used.
					+"PI"+s);//NM108 1/2 Identification Code Qualifier: PI=Payor Identification.
				sw.Write(Sout(GetCarrierElectID(carrier,clearhouse),80,2));//NM109 2/80 Identification Code: PayorID.
				EndSegment(sw);//NM110 through NM112 Not Used.
				//2010BB N3: (medical,institutional,dental) Payer Address.
				sw.Write("N3"+s+Sout(carrier.Address,55));//N301 1/55 Address Information:
				if(carrier.Address2!="") {
					sw.Write(s+Sout(carrier.Address2,55));//N302 1/55 Address Information: Required when there is a second address line.
				}
				EndSegment(sw);
				//2010BB N4: (medical,institutional,dental) Payer City, State, Zip Code.
				sw.Write("N4"+s
					+Sout(carrier.City,30)+s//N401 2/30 City Name:
					+Sout(carrier.State,2)+s//N402 2/2 State or Province Code:
					+Sout(carrier.Zip.Replace("-",""),15));//N403 3/15 Postal Code:
				EndSegment(sw);//N404 through N407 are either not used or are for addresses outside of the United States.
				//2010BB REF 2U,EI,FY,NF (dental) Payer Secondary Identificaiton. Situational.
				//2010BB REF G2,LU Billing Provider Secondary Identification. Situational. Not required because we always send NPI.
				if(!IsDentiCal(clearhouse)){//DentiCal complained that they don't usually want this (except for non-subparted NPIs, which we don't handle).  So far, nobody else has complained.
					//Always required by Emdeon Dental.
					WriteProv_REFG2orLU(sw,billProv,carrier.ElectID);
				}
				parentSubsc=HLcount;
				HLcount++;
				#endregion
				#region Patient
				if(patient.PatNum!=subscriber.PatNum){//if patient is not the subscriber
					//2000C HL: (medical,institutional,dental) Patient Hierarchical Level.
					sw.Write("HL"+s+HLcount.ToString()+s//HL01 1/12 Hierarchical ID Number:
						+parentSubsc.ToString()+s//HL02 1/12 Hierarchical Parent ID Number: Parent is always the subscriber HL.
						+"23"+s//HL03 1/2 Hierarchical Level Code: 23=Dependent.
						+"0");//HL04 1/1 Hierarchical Child Code: 0=No subordinate HL segment in this hierarchical structure.
					EndSegment(sw);
					//2000C PAT: (medical,institutional,dental) Patient Information.
					if(IsEmdeonDental(clearhouse)) {
						sw.Write("PAT"+s
							+GetRelat(claim.PatRelat)+s//PAT01 2/2 Individual Relationship Code:
							+s//PAT02 1/1 Patient Location Code: Not used.
							+s//PAT03 2/2 Employment Status Code: Not used.
							+GetStudentEmdeon(patient.StudentStatus));//PAT04 1/1 Student Status Code: Not used. Emdeon wants us to sent this code corresponding to version 4010, even through it is not standard X12.
						EndSegment(sw);//PAT05 through PAT08 not used in institutional or dental, but is sometimes used in medical. We do not use.
					}
					else {
						sw.Write("PAT"+s
							+GetRelat(claim.PatRelat));//PAT01 2/2 Individual Relationship Code:
						EndSegment(sw);//PAT02 through PAT04 Not used. PAT05 through PAT08 not used in institutional or dental, but is sometimes used in medical. We do not use.
					}
					//2010CA NM1: QC (medical,institutional,dental) Patient Name.
					sw.Write("NM1"+s
						+"QC"+s//NM101 2/3 Entity Identifier Code: QC=Patient.
						+"1"+s//NM102 1/1 Entity Type Qualifier: 1=Person.
						+Sout(patient.LName,60)+s//NM103 1/60 Name Last or Organization Name:
						+Sout(patient.FName,35));//NM104 1/35 Name First: Never blank, because validated in the patient edit window when a patient is added/edited.
						if(patient.MiddleI!="") {
							sw.Write(s+Sout(patient.MiddleI,25));//NM105 1/25 Name Middle
						}
					EndSegment(sw);
					//NM106 not used. NM107, No suffix field in Open Dental. NM108 through NM112 not used.
					//2010CA N3: (medical,institutional,dental) Patient Address.
					sw.Write("N3"+s+
						Sout(patient.Address,55));//N301 1/55 Address Information
					if(patient.Address2!="") {
						sw.Write(s+Sout(patient.Address2,55));//N302 1/55 Address Information:
					}
					EndSegment(sw);
					//2010CA N4: (medical,institutional,dental) Patient City, State, Zip Code.
					sw.Write("N4"+s
						+Sout(patient.City,30)+s//N401 2/30 City Name:
						+Sout(patient.State,2,2)+s//N402 2/2 State or Provice Code: 
						+Sout(patient.Zip.Replace("-",""),15));//N403 3/15 Postal Code: 
					EndSegment(sw);//N404 through N407 are either not used or only required for addresses outside the United States.
					//2010CA DMG: (medical,institutional,dental) Patient Demographic Information.
					sw.Write("DMG"+s
						+"D8"+s//DMG01 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD.
						+patient.Birthdate.ToString("yyyyMMdd")+s//DMG02 1/35 Date Time Period:
						+GetGender(patient.Gender));//DMG03 1/1 Gender Code: F=Female,M=Male,U=Unknown.
					EndSegment(sw);//DMG04 through DMG11 are not used.
					//2010CA REF: (medical,instituional,dental) Property and Casualty Claim Number. Situational. We do not use this.
					//2010CA REF: (medical,institutional) Property and Casualty Patient Identifier. Situational.  We do not use.
					//2010CA PER: (medical) Property and Casualty Patient Contact Information. Situational. We do not use.
					HLcount++;
				}
				#endregion
				#region Claim CLM
				//2300 CLM: (medical,institutional,dental) Claim Information.
				string clm01=claim.ClaimIdentifier;//Typically PatNum/ClaimNum. Check for uniqueness is performed in UI.
				if(IsDentiCal(clearhouse)) {
					clm01=Sout(clm01,17);//Denti-Cal has a maximum of 17 chars here. This field is what Denti-Cal refers to as the PDCN.
				}
				else if(IsEmdeonMedical(clearhouse)) {
					clm01=clm01.Replace('/','-');//Emdeon Medical only allows letters, numbers, dashes, periods, spaces and asterisks. The claim identifier will contain / inside the claim edit window still.
				}
				string claimFrequencyTypeCode="1";
				if(claim.CorrectionType==ClaimCorrectionType.Original) {
					claimFrequencyTypeCode="1";
				}
				else if(claim.CorrectionType==ClaimCorrectionType.Replacement) {
					claimFrequencyTypeCode="7";
				}
				else if(claim.CorrectionType==ClaimCorrectionType.Void) {
					claimFrequencyTypeCode="8";
				}
				//the next 8 lines fix a rare bug where the total doesn't match the sum of the procs.  This would result in invalid X12
				decimal claimFeeBilled=0;
				for(int j=0;j<claimProcs.Count;j++) {
					claimFeeBilled+=(decimal)claimProcs[j].FeeBilled;
				}
				if(claimFeeBilled!=(decimal)claim.ClaimFee) {
					claim.ClaimFee=(double)claimFeeBilled;
				  Claims.Update(claim);
				}
				sw.Write("CLM"+s
					+Sout(clm01,20)+s//CLM01 1/38 Claim Submitter's Identifier: A unique id. Carriers are not required to handle more than 20 char. 
					+claimFeeBilled.ToString("f2")+s//CLM02 1/18 Monetary Amount:
					+s//CLM03 1/2 Claim Filing Indicator Code: Not used.
					+s);//CLM04 1/2 Non-Institutional Claim Type Code: Not used.
				//CLM05 (medical,institutional,dental) Health Care Services Location Information.
				if(medType==EnumClaimMedType.Medical) {
					sw.Write(GetPlaceService(claim.PlaceService)+isa16//CLM05-1 1/2  Facility Code Value: Place of Service.
						+"B"+isa16//CLM05-2 1/2 Facility Code Qualifier, B=Place of Service Codes.
						+claimFrequencyTypeCode+s);//CLM05-3 1/1 Claim Frequency Type Code: 1=original, 7=replacement, 8=void(in limited jurisdictions).
				}
				else if(medType==EnumClaimMedType.Institutional) {
					//claim.UniformBillType validated to be exactly 3 char
					//Example: 771: 7=clinic, 7=FQHC, 1=Only claim.  713: 7=clinic, 1=rural health clinic, 3=continuing claim.
					sw.Write(claim.UniformBillType.Substring(0,2)+isa16//CLM05-1 1/2  Facility Code Value: First and second position of UniformBillType.
						+"A"+isa16//CLM05-2 1/2 Facility Code Qualifier, A=Uniform Billing Claim Form Bill Type.
						+claim.UniformBillType.Substring(2,1)+s);//CLM05-3 1/1 Claim Frequency Type Code: Third position of UniformBillType.
				}
				else{//dental.
					sw.Write(GetPlaceService(claim.PlaceService)+isa16//CLM05-1 1/2  Facility Code Value: Place of Service.
						+"B"+isa16//CLM05-2 1/2 Facility Code Qualifier, B=Place of Service Codes.
						+claimFrequencyTypeCode+s);//CLM05-3 1/1 Claim Frequency Type Code: 1=original, 7=replacement, 8=void(in limited jurisdictions).
				}
				if(medType==EnumClaimMedType.Medical) {
					sw.Write("Y"+s);//CLM06 1/1 Yes/No Condition or Response Code: prov sig on file (always yes)
				}
				else if(medType==EnumClaimMedType.Institutional) {
					sw.Write(s);//CLM06 1/1 Yes/No Condition or Response Code: Not used.
				}
				else if(medType==EnumClaimMedType.Dental) {
					sw.Write("Y"+s);//CLM06 1/1 Yes/No Condition or Response Code: prov sig on file (always yes)
				}
				sw.Write("A"+s//CLM07 1/1 Provider Accept Assignment Code: Prov accepts medicaid assignment. OD has no field for this, so no choice.
					+(sub.AssignBen?"Y":"N")+s//CLM08 1/1 Yes/No Condition or Response Code: We do not support W.
					+(sub.ReleaseInfo?"Y":"I"));//CLM09 1/1 Release of Information Code: Y or I(which is equivalent to No)
				if(medType==EnumClaimMedType.Medical || medType==EnumClaimMedType.Dental) {
					if(claim.AccidentDate.Year>1880 || claim.SpecialProgramCode!=EnumClaimSpecialProgram.none || claim.ClaimType=="PreAuth") {//if val for 11,12, or 19
						sw.Write(s+s//end of CLM09. CLM10 not used
							+GetRelatedCauses(claim));//CLM11 2/3:2/3:2/3:2/2:2/3 Related Causes Information: Situational. Accident related, including state. Might be blank.
					}
					if(claim.SpecialProgramCode!=EnumClaimSpecialProgram.none || claim.ClaimType=="PreAuth") {//if val for 12, or 19
						sw.Write(s//nothing for CLM11.
							+GetSpecialProgramCode(claim.SpecialProgramCode));//CLM12 2/3 Special Program Code: Situational. Example EPSTD.
					}
					if(claim.ClaimType=="PreAuth") {//if val for 19
						sw.Write(s//nothing for CLM12.
							+s+s+s+s+s+s//CLM13-18 not used
							+"PB");//CLM19 2/2 Claim Submission Reason Code: PB=Predetermination of Benefits. TODO: Not allowed in medical claims. What is the replacement??
						//CLM20 1/2 Delay Reason Code: Situational. Required when claim is submitted late. Not supported.
					}
				}
				//CLM10-19 not used, 20 not supported for institutional.
				EndSegment(sw);
				#endregion Claim CLM
				#region Claim DTP
				if(medType==EnumClaimMedType.Medical) {
					//2300 DTP: 431 (medical) Date Onset of Current Illness or Symptom. Situational. We do not use.
					//2300 DTP: 454 (medical) Initial Treatment Date. Situational. We do not use. (spinal manipulation).
					//2300 DTP: 304 (medical) Date Last Seen. Situational. We do not use. (foot care)
					//2300 DTP: 453 (medical) Date Accute Manifestation. Situational. We do not use. (spinal manipulation)
					//2300 DTP: 439 (medical) Date Accident. Situational.
					if(claim.AccidentDate.Year>1880) {
						sw.Write("DTP"+s
							+"439"+s//DTP01 3/3 Date/Time Qualifier: 439=accident
							+"D8"+s//DTP02 2/3 Date Time Period Format Qualifer: D8=Date Expressed in Format CCYYMMDD.
							+claim.AccidentDate.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period:
						EndSegment(sw);
					}
					//2300 DTP: 484 (medical) Last Menstrual Period Date. Situational. We do not use.
					//2300 DTP: 455 (medical) Last X-ray Date. Situational. We do not use.
					//2300 DTP: 471 (medical) Hearing and Vision Prescription Date. Situational. We do not use.
					//2300 DTP: 314,360,361 (medical) Disability Dates. Situational. We do not use.
					//2300 DTP: 297 (medical) Date Last Worked. Situational. We do not use.
					//2300 DTP: 296 (medical) Date Authorized Return to Work. Situational. We do not use.
					//2300 DTP: 435 (medical) Date Admission. Situational. We do not use. Inpatient. Request #2843.
					//2300 DTP: 096 (medical) Date Discharge. Situational. We do not use. Inpatient. Request #2843.
					//2300 DTP: 090 (medical) Date Assumed and Relinquished Care Dates. Situational. We do not use.
					//2300 DTP: 444 (medical) Date Property and Casualty Date of First Contact. Situational. We do not use.
					//2300 DTP: 050 (medical) Repricer Received Date. Situational. We do not use.
				}
				else if(medType==EnumClaimMedType.Institutional) {
					//2300 DTP 096 (institutional) Discharge Hour. Situational. We do not use. Inpatient. 
					//2300 DTP 434 (instititional) Statement Dates.
//todo:how to handle preauths?
					if(claim.DateService.Year>1880) {//DateService validated
						sw.Write("DTP"+s
							+"434"+s//DTP01 3/3 Date/Time Qualifier: 434=Statement.
							+"RD8"+s//DTP02 2/3 Date Time Period Format Qualifier: RD8=Range of Dates Expressed in Format CCYYMMDD-CCYYMMDD.
							+claim.DateService.ToString("yyyyMMdd")+"-"+claim.DateService.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period:
						EndSegment(sw);
					}
					//2300 DTP 435 (institutional) Admission Date/Hour. Situational. We do not use. Inpatient.
					//For the UB04 we are using claim.DateService for this field.
					//2300 DTP 050 (institutional) Repricer Received Date. Situational. Not supported.
				}
				else if(medType==EnumClaimMedType.Dental) {
					//2300 DTP 439 (dental) Date accident. Situational. Required when there was an accident.
					if(claim.AccidentDate.Year>1880) {
						sw.Write("DTP"+s
							+"439"+s//DTP01 3/3 Date/Time Qualifier: 439=accident
							+"D8"+s//DTP02 2/3 Date Time Period Format Qualifer: D8=Date Expressed in Format CCYYMMDD.
							+claim.AccidentDate.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period:
						EndSegment(sw);
					}
					//2300 DTP 452 (dental) Date Appliance Placement. Situational. Values can be overriden in loop 2400 for individual service items, but we don't support that.
					if(claim.OrthoDate.Year>1880) {
						sw.Write("DTP"+s
							+"452"+s//DTP01 3/3 Date/Time Qualifier: 452=Appliance Placement.
							+"D8"+s//DTP02 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD.
							+claim.OrthoDate.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period:
						EndSegment(sw);
					}
					//2300 DTP 472 (dental) Service Date. Not used if predeterm.
					if(claim.ClaimType!="PreAuth") {
						if(claim.DateService.Year>1880) {
							sw.Write("DTP"+s
								+"472"+s//DTP01 3/3 Date/Time Qualifier: 472=Service.
								+"D8"+s//DTP02 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD.
								+claim.DateService.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period:
							EndSegment(sw);
						}
					}
					//2300 DTP 050 (dental) Repricer Received Date.  Not supported.
				}
				#endregion Claim DTP
				#region Claim DN CL1
				if(medType==EnumClaimMedType.Dental) {
					//2300 DN1: Orthodontic Total Months of Treatment.
					if(claim.IsOrtho) {
						sw.Write("DN1"+s
							+s//DN101 1/15 Quantity: Total months of orthodontic treatment. Not used because no field yet in OD.
							+claim.OrthoRemainM.ToString());//DN102 1/15 Quantity: Number of treatment months remaining.
						EndSegment(sw);//DN103 is not used and DN104 is situational but we do not use it.
					}
					//2300 DN2: Tooth Status. Missing teeth.
					List<string> missingTeeth=ToothInitials.GetMissingOrHiddenTeeth(initialList);
					bool doSkip;
					int countMissing=0;
					for(int j=0;j<missingTeeth.Count;j++) {
						//if the missing tooth is missing because of an extraction being billed here, then exclude it
						//still needed, even though missing teeth are not based on procedures any longer
						doSkip=false;
						for(int p=0;p<claimProcs.Count;p++) {
							proc=Procedures.GetProcFromList(procList,claimProcs[p].ProcNum);
							procCode=ProcedureCodes.GetProcCode(proc.CodeNum);
							if(procCode.PaintType==ToothPaintingType.Extraction && proc.ToothNum==missingTeeth[j]) {
								doSkip=true;
								break;
							}
						}
						if(doSkip) {
							continue;
						}
						countMissing++;
						if(countMissing>35) {//segment max use 35
							continue;
						}
						sw.Write("DN2"+s
							+missingTeeth[j]+s//DN201 1/50 Reference Identification: Tooth number.
							+"M"+s//DN202: M=Missing, I=Impacted, E=To be extracted.
							+s//DN203 1/15 Quantity: Not used.
							+s//DN204 2/3 Date Time Period Format Qualifier: Not used.
							+s//DN205 1/35 Date Time Period: Not used.
							+"JP");//DN206 1/3 Code List Qualifier Code: Required. JP=JP Universal National Tooth Designation System.
						EndSegment(sw);
					}
				}
				if(medType==EnumClaimMedType.Institutional) {
					//2300 CL1: Institutional Claim Code. Required
					sw.Write("CL1"+s
						+claim.AdmissionTypeCode+s//CL101 1/1 Admission Type Code: Validated.
						+claim.AdmissionSourceCode+s//CL102 1/1 Admission Source Code: Required for inpatient services. Validated.
						+claim.PatientStatusCode);//CL103 1/2 Patient Status Code: Validated.
					EndSegment(sw);//CL104 1/1 Nursing Home Residential Status Code: Not used.
				}
				#endregion Claim DN CL1
				#region Claim PWK
				//2300 PWK: (medical,institutional,dental) Claim Supplemental Information. Paperwork. Used to identify attachments.
				/*if(IsTesia(clearhouse) && claim.Attachments.Count>0) {//If Tesia and has attachments
					sw.Write("PWK"+s
						+"OZ"+s//PWK01: ReportTypeCode. OZ=Support data for claim.
						+"EL"+s//PWK02: Report Transmission Code. EL=Electronic
						+s+s//PWK03 and 04: not used
						+"AC"+s//PWK05: Identification Code Qualifier. AC=Attachment Control Number
						+"TES"+claim.ClaimNum.ToString());//PWK06: Identification Code.
				 	EndSegment(sw);
				}*/
				//If Attachment ID # is present but no attachment flag, then sending is blocked.
				//No other validation is done.  However, warnings are displayed if:
				//Warning if attachments are listed as Mail even though we are sending electronically.
				//Warning if any PWK segments are needed, and there is no ID code.
				//PWK can repeat max 10 times.  However, we only write one PWK segment, because the user can only enter one Attachment Control Number.
				string pwk01="  ";//This double blank will never actually get sent because of the trim and if statement around the PWK creation.
				if(claim.AttachedFlags.Contains("EoB")) {
					pwk01="EB";//Explaination of Benefits
				}
				if(claim.AttachedFlags.Contains("Perio")) {
					if(medType==EnumClaimMedType.Dental) {
						pwk01="P6";//Periodontal Charts
					}
					else {//Medical and institutional
						pwk01="OZ";//Support Data for Claim. There is no "P6" nor a code for perio charts.
					}
				}
				if(claim.AttachedFlags.Contains("Misc") || claim.AttachedFlags.Contains("Note") || claim.AttachedImages>0) {
					pwk01="OZ";//Support Data for Claim
				}
				if(claim.Radiographs>0) {
					pwk01="RB";//Radiology Films
				}
				if(claim.AttachedModels>0) {
					pwk01="DA";//Dental Models
				}
				string pwk02="  ";
				if(IsDentiCal(clearhouse)) {
					pwk02="FT";//"File Transfer". Might be electronic or mail, but Denti-Cal requires a value of FT here.
				}
				else {
					if(claim.AttachedFlags.Contains("Mail")) {
						pwk02="BM";//By Mail
					}
					else {
						pwk02="EL";//Elect
					}
				}
				string pwk06=claim.AttachmentID;
				if(pwk02=="BM" && pwk06=="") {//If By Mail is checked, they will typically leave attachment ID blank, but X12 requires a value, so we make one up.
					pwk06="00";
				}
				pwk06=Sout(pwk06,80,2);
				if(pwk01.Trim()!="" && pwk06!="") {
					sw.Write("PWK"+s
						+pwk01+s//PWK01 2/2 Report Type Code:
						+pwk02+s//PWK02 1/2 Report Transmission Code: EL=Electronically Only, BM=By Mail.
						+s+s//PWK03 and PWK04: Not Used.
						+"AC"+s//PWK05 1/2 Identification Code Qualifier: AC=Attachment Control Number.
						+pwk06);//PWK06 2/80 Identification Code:
					EndSegment(sw);//PWK07 through PWK09 are not used.
				}
				#endregion Claim PWK
				#region Claim CN1 AMT
				//2300 CN1: (medical,institutional,dental)Contract Information. Situational. We do not use this.
				//2300 AMT: (institutional) Patient Estimated Amount Due.
				//2300 AMT: (medical,dental) Patient Amount Paid. Situational. We do not use this.
				if(medType==EnumClaimMedType.Medical || medType==EnumClaimMedType.Dental) {
					//sw.Write("AMT"+s
				  //  +"F5"+s//AMT01 1/3 Amount Qualifier Code: F5=Patient Paid Amount.
				  //  +"0");//AMT02 1/18 Monetary Amount: We don't track this information very well so we always put zero.
					//EndSegment(sw);//AMT03 is not used.
				}
				#endregion Claim CN1 AMT
				#region Claim REF
				if(medType==EnumClaimMedType.Dental) {
					//2300 REF: G3 (dental) Predetermination Identification. Situational.  Required when sending claim for previously predetermined services. Do not send prior authorization number here.
					if(claim.PreAuthString!="") {//validated to be empty for medical and inst
						sw.Write("REF"+s
							+"G3"+s//REF01 2/3 G3=Predetermination of Benefits Identification Number.
							+Sout(claim.PreAuthString,50));//REF02 1/50 Predeterm of Benfits Identifier.
						EndSegment(sw);//REF03 and REF04 are not used.
					}
				}
				//2300 REF: 4N (medical,institutional,dental) Service Authorization Exception Code. Situational. Required if services were performed without authorization.
//todo: ServiceAuthException
				//2300 REF: F5 (medical) Mandatory Medicare (Section 4081) Crossover Indicator. Situational. Required when submitter is Medicare and the claim is a Medigap or COB crossover claim. We do not use.
				//2300 REF: EW (medical) Mammography Certification Number. Situational. We do not use.
				//2300 REF: F8 (medical,institutional,dental) Payer Claim Control Number: Situational. Required if this is a replacement or void claim. Might not be required for corrected, but we require anyway since it is required in 4010.
					//aka Original Document Control Number/Internal Control Number (DCN/ICN).
					//aka Transaction Control Number (TCN).  
					//aka Claim Reference Number. 
					//Seems to be required by Medicaid when voiding a claim or resubmitting a claim by setting the CLM05-3.
				if(claim.CorrectionType!=ClaimCorrectionType.Original 
					|| claim.UniformBillType.Length>2 && (claim.UniformBillType.Substring(2,1)=="6" || claim.UniformBillType.Substring(2,1)=="7" || claim.UniformBillType.Substring(2,1)=="8")) { //correction, replacement or void.
					sw.Write("REF"+s
						+"F8"+s//REF01 2/3 Reference Identification Qualifier: F8=Original Reference Number.
						+Sout(claim.OrigRefNum,50));//REF02 1/50 Reference Identification: Payer Claim Control Number.
					EndSegment(sw);//REF03 and REF04 are not used.
				}
				//2300 REF: 9F (medical,institutional,dental) Referral Number. Situational. Required when a referral number is assigned by the payer or Utilization Management Organization (UMO) AND a referral is involved.
				if(claim.RefNumString!="") {
					sw.Write("REF"+s
						+"9F"+s//REF01 2/3 Reference Identification Qualifier: 9F=Referral Number.
						+Sout(claim.RefNumString,30));//REF02 1/50 Reference Identification:
					EndSegment(sw);//REF03 and REF04 are not used.
				}
				//2300 REF: X4 (medical) Clinical Laboratory Improvement Amendment (CLIA) Number. Situational. We do not use.
				//2300 REF: G1 (medical,institutional,dental) Prior Authorization. Situational. Do not report predetermination of benefits id number here. G1 and G3 were muddled in 4010.  
				if(claim.PriorAuthorizationNumber!="") {
					sw.Write("REF"+s
						+"G1"+s//REF01 2/3 Reference Identification Qualifier: G1=Prior Authorization Number.
						+Sout(claim.PriorAuthorizationNumber,50));//REF02 1/50 Reference Identification: Prior Authorization Number.
					EndSegment(sw);//REF03 and REF04 are not used.
				}					
				//2300 REF: 9A (medical,institutional,dental) Repriced Claim Number. Situational. We do not use. 
				//2300 REF: 9C (medical,institutional,dental) Adjusted Repriced Claim Number. Situational. We do not use.
				//2300 REF: D9 (medical,institutional,dental) Claim Identifier For Transmission Intermediaries. Situational.
				if(IsClaimConnect(clearhouse)) { //Since this information has only been requested by ClaimConnect and is optional in the specification, we should only add specific clearinghouses here when requested.
					sw.Write("REF"+s
						+"D9"+s//REF01 2/3 Reference Identification Qualifier: D9=Claim Number.
						+Sout(claim.ClaimIdentifier,20));//REF02 1/50 Reference Identification: Value Added Network Trace Number. From specification, maximum of 20 characters even though there is space for 50.
					EndSegment(sw);//REF03 and REF04 are not used.
				}
				//2300 REF: LX (medical,institutional) Investigational Device Exemption Number. Situational. Required for FDA IDE.
				//2300 REF: LU (institutional) Auto Accident State. Situational. Seems to me to be a duplicate of the info in CLM11.
				//2300 REF: EA (medical,institutional) Medical Record Number. Situational. We do not use.
				//2300 REF: P4 (medical,institutional) Demonstration Project Identifier. Situational. We do not use. Seems very unimportant.
				//2300 REF: G4 (institutional) Peer Review Organization (PRO) Approval Number. Situational. We do not use.
				//2300 REF: 1J (medical) Care Plan Oversight. Situational. We do not use.
				#endregion Claim REF
				#region Claim K3 NTE CRx
				//2300 K3: File info (medical,institutional,dental). Situational. We do not use this.
				//NTE loops------------------------------------------------------------------------------------------------------
				//2300 NTE: (medical,institutional,dental) Claim Note. Situational. A number of NTE01 codes other than 'ADD', which we don't support.
				string note="";
				if(claim.AttachmentID!="" && !claim.ClaimNote.StartsWith(claim.AttachmentID)) {
					note=claim.AttachmentID+" ";
				}
				note+=claim.ClaimNote;
				if(note!="") {
					sw.Write("NTE"+s
						+"ADD"+s//NTE01 3/3 Note Reference Code: ADD=Additional information.
						+Sout(note,80));//NTE02 1/80 Description:
					EndSegment(sw);
				}
				//2300 NTE: (institutional) Billing Note. Situational. We do not use.
				//CRx loops------------------------------------------------------------------------------------------------------
				//2300 CR1: LB (medical) Ambulance Transport Information. Situational. We do not use.
				//2300 CR2: (medical) Spinal Manipulation Service Information. Situational. We do not use.
				//2300 CRC: (medical) Ambulance Certification. Situational. We do not use.
				//2300 CRC: (medical) Patient Condition Information Vision. Situational. We do not use.
				//2300 CRC: (medcial) Homebound Indicator. Situational. We do not use.
				//2300 CRC: (medical,institutional) EPSDT Referral. Situational. Required on EPSDT claims when the screening service is being billed in this claim. We do not use.
				#endregion Claim K3 NTE CRx
				#region Claim HI HCP
				//HI loops-------------------------------------------------------------------------------------------------------
				List<string> diagnosisList=new List<string>();//princDiag will always be the first element.
				if(medType==EnumClaimMedType.Medical || medType==EnumClaimMedType.Institutional){
					for(int j=0;j<claimProcs.Count;j++) {
						proc=Procedures.GetProcFromList(procList,claimProcs[j].ProcNum);
						if(proc.DiagnosticCode=="") {
							continue;
						}
						if(proc.IsPrincDiag) {
							if(diagnosisList.Contains(proc.DiagnosticCode)) {
								diagnosisList.Remove(proc.DiagnosticCode);
							}
							diagnosisList.Insert(0,proc.DiagnosticCode);//princDiag always goes first. There will always be one.
						}
						else {//not princDiag
							if(!diagnosisList.Contains(proc.DiagnosticCode)) {
								diagnosisList.Add(proc.DiagnosticCode);
							}
						}
					}
				}
				//2300 HI: BK (medical,dental) Health Care Diagnosis Code. Situational. For OMS or anesthesiology.
//todo: validate at least one diagnosis
				if(medType==EnumClaimMedType.Institutional) {
					sw.Write("HI"+s
						+"BK"+isa16//HI01-1 1/3 Code List Qualifier Code: BK=ICD-9 Principal Diagnosis.
						+Sout(diagnosisList[0].Replace(".",""),30));//HI01-2 1/30 Industry Code: Diagnosis code. No periods.
					EndSegment(sw);
				} 
				else if(medType==EnumClaimMedType.Medical) {
					sw.Write("HI"+s
						+"BK"+isa16//HI01-1 1/3 Code List Qualifier Code: BK=ICD-9 Principal Diagnosis.
						+Sout(diagnosisList[0].Replace(".",""),30));//HI01-2 1/30 Industry Code: Diagnosis code. No periods.
					for(int j=1;j<diagnosisList.Count;j++) {
						if(j>11) {//maximum of 12 diagnoses
							break;
						}
						sw.Write(s//this is the separator from the _previous_ field.
							+"BF"+isa16//HI0#-1 1/3 Code List Qualifier Code: BF=ICD-9 Diagnosis
							+Sout(diagnosisList[j].Replace(".",""),30));//HI0#-2 1/30 Industry Code: Diagnosis code. No periods.
					}
					EndSegment(sw);
				}
				//2300 HI: BP (medical) Anesthesia Related Procedure. Situational. We do not use.
				//2300 HI: BJ (institutional) Admitting Diagnosis. Situational. Required for inpatient admission. We do not use.
				//2300 HI: PR (institutional) Patient's Reason for Visit. Situational. Required for outpatient visits.
				if(medType==EnumClaimMedType.Institutional) {
					sw.Write("HI"+s
						+"PR"+isa16//HI01-1 1/3 Code List Qualifier Code: PR=ICD-9 Patient's Reason for Visit.
						+Sout(diagnosisList[0].Replace(".",""),30));//HI01-2 1/30 Industry Code: No periods. This is not really principal diagnosis but is close to the same, so someday we will add this field to claim.
					EndSegment(sw);
				}
				//2300 HI: BN (institutional) External Cause of Injury. Situational. We do not use.
				//2300 HI: (institutional) Diagnosis Related Group (DRG) Information. Situational. We do not use. For inpatient hospital under DRG contract.
				//2300 HI: BF (institutional) Other Diagnosis Information. Situational. We do not use. When other conditions coexist or develop.
				//2300 HI: BR (institutional) Principal Procedure Information. Situational. We do not use. Required on inpatient claims when a procedure was performed.
				//2300 HI: BQ (institutional) Other Procedure Information. Situational. We do not use. Inpatient claims for additional procedures.
				//2300 HI: BI (institutional) Occurence Span Information. Situational. We do not use. For an occurence span code.
				//2300 HI: BH (institutional) Occurence Information. Situational. We do not use. For an occurence code.
				//2300 HI: BE (institutional) Value Information. Situational. We do not use. For a value code.
				//2300 HI: BG (medical,institutional) Condition Information. Situational. We do not use. For a condition code.
				//2300 HI: TC (institutional) Treatment Code Information. Situational. We do not use. When home health agencies need to report plan of treatment information under contracts.
				//2300 HCP: (medical,institutional,dental) Claim Pricing/Repricing Information. Situational. We do not use.
				#endregion Claim HI HCP
				bool sendFacilityNameAndAddress=false;
				if(medType==EnumClaimMedType.Medical) {
					//Code added to send the segment below, but no logic here for sending yet, so it is never sent.
				}
				else if(medType==EnumClaimMedType.Institutional) {
					//Code added to send the segment below, but no logic here for sending yet, so it is never sent.
				}
				else if(medType==EnumClaimMedType.Dental) {
					if(claim.PlaceService!=PlaceOfService.Office) {
						if(IsClaimConnect(clearhouse)) {
							//Osvaldo Ferrer, VIP account manager for DentalXChange, says we need the segment whenever the place of service is not office.
							sendFacilityNameAndAddress=true;
						}
						else {//for other clearinghouses, the X12 specs say that we don't send it if it's the same as the billing prov.
							//and since we always set it the same as the billing prov, we shouldn't send it.
						}
					}
				}
				Provider facilityProv=billProv;//If this provider changes in the future, then the validation section will also need to be updated.
				string facilityAddress1=billingAddress1;
				string facilityAddress2=billingAddress2;
				string facilityCity=billingCity;
				string facilityState=billingState;
				string facilityZip=billingZip;
				//For medical, instititional, and dental, sending facility NPI must be for an organization (non-person).
				if(!facilityProv.IsNotPerson) {//Validated also
					sendFacilityNameAndAddress=false;
				}
				provTreat=Providers.GetProv(claim.ProvTreat);
				#region 2310 Claim Providers (medical)
				//Since order might be important, we have to handle medical, institutional, and dental separately.
				if(medType==EnumClaimMedType.Medical) {
					//2310A NM1: DN/P3 (medical) Referring Provider Name. Situational.
					WriteNM1_DN(sw,claim.ReferringProv);
					//2310A REF: (medical) Referring Provider Secondary Identification. Situational. We do not use.
					//Always included for Emdeon Medical, because Emdeon Medical will automatically remove this segment if the payer does not want it
					//Some payers reject if not specified, even when the claim.ProvTreat=claim.ProvBill. For example, Texas Medicaid.
					//if(claim.ProvTreat!=claim.ProvBill || IsEmdeonMedical(clearhouse)) {
					//2310B NM1: 82 (medical) Rendering Provider Name. Required when treating provider is different from billing provider.
					WriteNM1Provider("82",sw,provTreat);
					//2310B PRV: PE (medical) Rendering Provider Specialty Information. Situational.
					WritePRV_PE(sw,provTreat);
					//2310B REF: (medical) Rendering Provider Secondary Identification. Situational. We do not use.					
					//2310C NM1: 77 (medical) Service Facility Location Name. Conditions different than 4010.  
					//Not supposed to send if same location as 2010AA Billing Provider, but some clearinghouses want this segment anyway.
					if(sendFacilityNameAndAddress) {
						sw.Write("NM1"+s
							+"77"+s//NM101 2/3 Entity Identifier Code: 77=Service Location.
							+"2"+s//NM102 1/1 Entity Type Qualifier: 2=Non-Person Entity.
							+Sout(facilityProv.LName,60)+s//NM103 1/60 Name Last or Organization Name: Laboratory or Facility Name.
							+s//NM104 1/35 Name First: Not used.
							+s//NM105 1/25 Name Middle: Not used.
							+s//NM106 1/10 Name Prefix: Not used.
							+s//NM107 1/10 Name Suffix: Not used.
							+"XX"+s//NM108 1/2 Identification Code Qualifier: XX=NPI.
							+Sout(facilityProv.NationalProvID,80));//NM109 2/80 Identification Code: Laboratory or Facility Identifier. Validated.
						EndSegment(sw);//NM110 through NM112 not used.
						//2310C N3: (medical) Service Facility Location Address.
						sw.Write("N3"+s+Sout(facilityAddress1,55));//N301 1/55 Address Information: Laboratory or Facility Address Line.
						if(facilityAddress2!="") {
							sw.Write(s+Sout(facilityAddress2,55));//N302 1/55 Address Information: Laboratory or Facility Address Line 2. Only required when there is a secondary address line.
						}
						EndSegment(sw);
						//2310C N4: (medical) Service Facility Location City, State, Zip Code.
						sw.Write("N4"+s
							+Sout(facilityCity,30)+s//N401 2/30 City Name: Laboratory or Facility City Name.
							+Sout(facilityState,2,2)+s//N402 2/2 State or Provice Code: Laboratory or Facility State or Province Code.
							+Sout(facilityZip.Replace("-",""),15));//N403 3/15 Postal Code: Laboratory or Facility Postal Zone or ZIP Code.
						EndSegment(sw);//N404 through N407 are either not used or only required when outside of the United States.
						//2310C REF: (medical) Service Facility Location Secondary Identification. Situational. We do not use this.
						//2310C PER: (medical) Service Facility Contact Information. Situational. Required for property and casualty claims. We do not use.
					}
					//2310D NM1: (medical) Supervising Provider Name. Situational. We do not use.
					//2310D REF: (medical) Supervising Provider Secondary Identification. Situational. We do not use.
					//2310E NM1: (medical) Ambulance Pick-up Location. Situational. We do not use.
					//2310E N3: (medical) Ambulance Pick-up Location Address. We do not use.
					//2310E N4: (medical) Ambulance Pick-up Location City, State, Zip Code. We do not use.
					//2310F NM1: (medical) Ambulance Drop-off Location. Situational. We do not use.
					//2310F N3: (medical) Ambulance Drop-off Location Address. We do not use.
					//2310F N4: (medical) Ambulance Drop-off Location City, State, Zip Code. We do not use.
				}
				#endregion 2310 Claim Providers (medical)
				#region 2310 Claim Providers (inst)
				if(medType==EnumClaimMedType.Institutional) {
					//2310A NM1: 71 (institutional) Attending Provider Name. Situational. Always a person according to the specification (cannot be non-person).
					WriteNM1Provider("71",sw,provTreat.FName,provTreat.MI,provTreat.LName,provTreat.NationalProvID,false);
					//2310A PRV: AT (institutional) Attending Provider Specialty Information. Situational.
					sw.Write("PRV"+s
						+"AT"+s//PRV01 1/3 Provider Code: AT=Attending.
						+"PXC"+s//PRV02 2/3 Reference Identification Qualifier: PXC=Health Care Provider Taxonomy Code.
						+X12Generator.GetTaxonomy(provTreat));//PRV03 1/50 Reference Identification: Provider Taxonomy Code.
					EndSegment(sw);//PRV04 through PRV06 are not used.
					//2310A REF: (institutional) Attending Provider Secondary Identification. Situational.
					//2310B NM1: 72 (institutional) Operating Physician Name. Situational. For surgical procedure codes.
					//2310C REF: ZZ (institutional) Secondary Physician Secondary Identification. Situational.
					//2310C NM1: ZZ (institutional) Other Operating Physician Name. Situational.
					//2310C REF: ZZ (institutional) Other Operating Physician Secondary Identification. Situational.
					//2310D NM1: 82 (institutional) Rendering Provider Name. Situational. If different from attending provider AND when regulations require both facility and professional components.
					//2310D REF: ZZ (institutional) Rendering Provider Secondary Identificaiton. Situational.
					//2310E NM1: 77 (institutional) Service Facility Location Name. Conditions different than 4010.  
					//Not supposed to send if same location as 2010AA Billing Provider, but some clearinghouses want this segment anyway.
					if(sendFacilityNameAndAddress) {
						sw.Write("NM1"+s
							+"77"+s//NM101 2/3 Entity Identifier Code: 77=Service Location.
							+"2"+s//NM102 1/1 Entity Type Qualifier: 2=Non-Person Entity.
							+Sout(facilityProv.LName,60)+s//NM103 1/60 Name Last or Organization Name: Laboratory or Facility Name.
							+s//NM104 1/35 Name First: Not used.
							+s//NM105 1/25 Name Middle: Not used.
							+s//NM106 1/10 Name Prefix: Not used.
							+s//NM107 1/10 Name Suffix: Not used.
							+"XX"+s//NM108 1/2 Identification Code Qualifier: XX=NPI.
							+Sout(facilityProv.NationalProvID,80));//NM109 2/80 Identification Code: Laboratory or Facility Primary Identifier. Validated.
						EndSegment(sw);//NM110 through NM112 not used.
						//2310E N3: (institutional) Service Facility Location Address.
						sw.Write("N3"+s+Sout(facilityAddress1,55));//N301 1/55 Address Information: Laboratory or Facility Address Line.
						if(facilityAddress2!="") {
							sw.Write(s+Sout(facilityAddress2,55));//N302 1/55 Address Information: Laboratory or Facility Address Line 2. Only required when there is a secondary address line.
						}
						EndSegment(sw);
						//2310E N4: (institutional) Service Facility Location City, State, Zip Code.
						sw.Write("N4"+s
							+Sout(facilityCity,30)+s//N401 2/30 City Name: Laboratory or Facility City Name.
							+Sout(facilityState,2,2)+s//N402 2/2 State or Provice Code: Laboratory or Facility State or Province Code.
							+Sout(facilityZip.Replace("-",""),15));//N403 3/15 Postal Code: Laboratory or Facility Postal Zone or ZIP Code.
						EndSegment(sw);//N404 through N407 are either not used or only required when outside of the United States.
						//2310E REF: ZZ (institutional) Service Facility Location Secondary Identificiation. Situational. We do not use.
					}
					//2310F NM1: DN (institutional) Referring Provider Name. Situational. Required when referring provider is different from attending provider.
					if(claim.ReferringProv!=claim.ProvTreat) {
						WriteNM1_DN(sw,claim.ReferringProv);
					}
					//2310F REF: (institutional) Referring Provider Secondary Identification. Situational. 
				}
				#endregion 2310 Claim Providers (inst)
				#region 2310 Claim Providers (dental)
				if(medType==EnumClaimMedType.Dental) {
					//2310A NM1: DN (dental) Referring Provider Name. Situational.
					WriteNM1_DN(sw,claim.ReferringProv);
					//2310A PRV: (dental) Referring Provider Specialty Information. Situational.
					//2310A REF: G2 (dental) Referring Provider Secondary Identification. Situational.
					bool sendClaimTreatProv=false;
					if(claim.ProvTreat!=claim.ProvBill) { //Emdeon will reject the claim if this segment is the same as the billing provider for all claims in the batch.
						sendClaimTreatProv=true;//Standard X12 behavior to only include the treating provider if it is different than the billing provider.
					}
					//The following clearinghouses always want the claim treating provider, even if it is the same as the billing provider.
					if(IsOfficeAlly(clearhouse)) {
						sendClaimTreatProv=true;
					}
					if(sendClaimTreatProv) {
						//2310B NM1: 82 (dental) Rendering Provider Name. Situational. Only required if different from the billing provider.
						WriteNM1Provider("82",sw,provTreat);
						//2310B PRV: PE (dental) Rendering Provider Specialty Information.
						WritePRV_PE(sw,provTreat);
						//2310B REF: (dental) Rendering Provider Secondary Identification. Situational. Not required because we always send NPI. Max repeat of 4.
						if(IsClaimConnect(clearhouse) || IsEmdeonDental(clearhouse)) {
							//The state licence number can be anywhere between 4 and 14 characters depending on state, and most states have more than one state license format. 
							//Therefore, we only validate that the state license is present or not.
							if(provTreat.StateLicense!="") { 
								sw.Write("REF"+s
									+"0B"+s//REF01 2/3 Reference Identification Qualifier: 0B=State License Number.
									+Sout(provTreat.StateLicense,50));//REF02 1/50 Reference Identification:
								EndSegment(sw);//REF03 and REF04 are not used.
							}
						}
						if(IsEmdeonDental(clearhouse)) { //Always required by Emdeon Dental.
							WriteProv_REFG2orLU(sw,provTreat,carrier.ElectID);
						}
					}
					//2310C NM1: 77 (dental) Service Facility Location Name. Conditions different than 4010.  
					//Not supposed to send if same location as 2010AA Billing Provider, but ClaimConnect wants this segment anyway.
					if(sendFacilityNameAndAddress) {
						sw.Write("NM1"+s
							+"77"+s//NM101 2/3 Entity Identifier Code: 77=Service Location.
							+"2"+s//NM102 1/1 Entity Type Qualifier: 2=Non-Person Entity.
							+Sout(facilityProv.LName,60)+s//NM103 1/60 Name Last or Organization Name: Laboratory or Facility Name.
							+s//NM104 1/35 Name First: Not used.
							+s//NM105 1/25 Name Middle: Not used.
							+s//NM106 1/10 Name Prefix: Not used.
							+s//NM107 1/10 Name Suffix: Not used.
							+"XX"+s//NM108 1/2 Identification Code Qualifier: XX=NPI.
							+Sout(facilityProv.NationalProvID,80));//NM109 2/80 Identification Code: Laboratory or Facility Identifier. Validated.
						EndSegment(sw);//NM110 through NM112 not used.
						//2310C N3: (dental) Service Facility Location Address.
						sw.Write("N3"+s+Sout(facilityAddress1,55));//N301 1/55 Address Information: Laboratory or Facility Address Line.
						if(facilityAddress2!="") {
							sw.Write(s+Sout(facilityAddress2,55));//N302 1/55 Address Information: Laboratory or Facility Address Line 2. Only required when there is a secondary address line.
						}
						EndSegment(sw);
						//2310C N4: (dental) Service Facility Location City, State, Zip Code.
						sw.Write("N4"+s
							+Sout(facilityCity,30)+s//N401 2/30 City Name: Laboratory or Facility City Name.
							+Sout(facilityState,2,2)+s//N402 2/2 State or Provice Code: Laboratory or Facility State or Province Code.
							+Sout(facilityZip.Replace("-",""),15));//N403 3/15 Postal Code: Laboratory or Facility Postal Zone or ZIP Code.
						EndSegment(sw);//N404 through N407 are either not used or only required when outside of the United States.
						//2310C REF: (dental) Service Facility Location Secondary Identification. Situational. We do not use this.
					}
					//2310D NM1: (dental) Assistant Surgeon Name. Situational. We do not support.
					//2310D PRV: (dental) Assistant Surgeon Specialty Information. We do not support.
					//2310D REF: (dental) Assistant Surgeon Secondary Identification. We do not support.
					//2310E NM1: (dental) Supervising Provider Name. Situational. We do not support.
					//2310E REF: (dental) Supervising Provider Secondary Identification. Situational. We do not support.
				}
				#endregion 2310 Claim Providers (dental)
				#region 2320 Other subscriber information
				List<double> listProcWriteoffAmts=new List<double>();
				List<double> listProcDeductibleAmts=new List<double>();
				List<double> listProcPaidOtherInsAmts=new List<double>();
				bool hasAdjForOtherPlans=false;
				//2320 Other subscriber------------------------------------------------------------------------------------------
				if(otherPlan!=null) {
					//2320 SBR: Other Subscriber Information. Situational.
					sw.Write("SBR"+s);
					sw.Write((claimIsPrimary?"S":"P")+s);//SBR01 1/1 Payer Responsibility Sequence Number Code: When the claim is primary then the other insurance is secondary, and vice versa.
					sw.Write(GetRelat(claim.PatRelat2)+s//SBR02 2/2 Individual Relationship Code:
						+Sout(otherPlan.GroupNum,50)+s);//SBR03 1/50 Reference Identification:
					//SBR04 1/60 Name: Situational. Required when SBR03 is not specified.
					if(otherPlan.GroupNum!="") {
						sw.Write(s);
					}
					else {
						sw.Write(Sout(otherPlan.GroupName,60)+s);
					}
					sw.Write(s//SBR05 1/3 Insurance Type Code: Situational. Required when the payer in loop 2330B is Medicare and Medicare is not the primary payer. Medical and Dental only. TODO: implement.
						+s//SBR06 1/1 Coordination of Benefits Code: Not used.
						+s//SBR07 1/1 Yes/No Condition or Response Code: Not Used.
						+s//SBR08 2/2 Employment Status Code: Not Used.
						+GetFilingCode(otherPlan));//SBR09 1/2 Claim Filing Indicator Code: 12=PPO,17=DMO,BL=BCBS,CI=CommercialIns,FI=FEP,HM=HMO. Will no longer be required when HIPPA National Plan ID is mandated.
					EndSegment(sw);
					double claimWriteoffAmt=0;
					double claimDeductibleAmt=0;
					double claimPaidOtherInsAmt=0;
					double claimPatientPortionAmt=0;
					for(int j=0;j<claimProcs.Count;j++) {//Claim procs for this claim
						double procWriteoffAmt=0;
						double procDeductibleAmt=0;
						double procPaidOtherInsAmt=0;
						for(int k=0;k<claimProcList.Count;k++) {//All claim procs for patient
							if(ClaimProcs.IsValidClaimAdj(claimProcList[k],claimProcs[j].ProcNum,claimProcs[j].InsSubNum)) {//Adjustment due to other insurance plans.
								hasAdjForOtherPlans=true;
								claimWriteoffAmt+=claimProcList[k].WriteOff;
								claimDeductibleAmt+=claimProcList[k].DedApplied;
								claimPaidOtherInsAmt+=claimProcList[k].InsPayAmt;
								procWriteoffAmt+=claimProcList[k].WriteOff;
								procDeductibleAmt+=claimProcList[k].DedApplied;
								procPaidOtherInsAmt+=claimProcList[k].InsPayAmt;
							}
						}
						listProcWriteoffAmts.Add(procWriteoffAmt);
						listProcDeductibleAmts.Add(procDeductibleAmt);
						listProcPaidOtherInsAmts.Add(procPaidOtherInsAmt);
						double procPatientPortionAmt=Math.Max(0,claimProcs[j].FeeBilled-listProcWriteoffAmts[j]-listProcDeductibleAmts[j]-listProcPaidOtherInsAmts[j]);
						claimPatientPortionAmt+=procPatientPortionAmt;
					}
					//If sending the primary claim, then hasAdjForOtherPlans will be false, because all claimprocs for any other plans (secondary) will be estimates.
					//If sending the secondary claim, then hasAdjForOtherPlans will be true, because the primary claimprocs will be received.
					//This strategy works for dental and medical plans in any combination: D, M, DD, DM, MD, MM
					if(hasAdjForOtherPlans) {
						//2320 CAS: (medical,institutional,dental) Claim Level Adjustments. Situational. We use this to show patient responsibility, because the adjustments here plus AMT D below must equal claim amount in CLM02 for Emdeon.
						//Claim Adjustment Reason Codes can be found on the Washington Publishing Company website at: http://www.wpc-edi.com/reference/codelists/healthcare/claim-adjustment-reason-codes/
						if(claimWriteoffAmt>0) {
							sw.Write("CAS"+s
								+"CO"+s//CAS01 1/2 Claim Adjustment Group Code: CO=Contractual Obligations.
								+"45"+s//CAS02 1/5 Claim Adjustment Reason Code: 45=Charge exceeds fee schedule/maximum allowable or contracted/legislated fee arrangement.
								+AmountToStrNoLeading(claimWriteoffAmt));//CAS03 1/18 Monetary Amount:
							EndSegment(sw);
						}
						if(claimDeductibleAmt>0 || claimPatientPortionAmt>0) {
							sw.Write("CAS"+s
								+"PR");//CAS01 1/2 Claim Adjustment Group Code: PR=Patient Responsibility.
							if(claimDeductibleAmt>0) {
								sw.Write(s//end of previous field
									+"1"+s//CAS02 1/5 Claim Adjustment Reason Code: 1=Deductible.
									+AmountToStrNoLeading(claimDeductibleAmt)+s//CAS03 1/18 Monetary Amount:
									+"1");//CAS04 1/15 Quantity:
							}
							if(claimPatientPortionAmt>0) {
								sw.Write(s//end of previous field
									+"3"+s//CAS02 or CAS05 1/5 Claim Adjustment Reason Code: 3=Co-payment Amount.
									+AmountToStrNoLeading(claimPatientPortionAmt));//CAS03 or CAS06 1/18 Monetary Amount:
							}
							EndSegment(sw);
						}
						//2320 AMT: D (medical,institutional,dental) COB Payer Paid Amount. Situational. Required when the claim has been adjudicated by payer in loop 2330B.
						sw.Write("AMT"+s
							+"D"+s//AMT01 1/3 Amount Qualifier Code: D=Payor Amount Paid.
							+AmountToStrNoLeading(claimPaidOtherInsAmt));//AMT02 1/18 Monetary Amount:
						EndSegment(sw);//AMT03 Not used.
						//2320 AMT: EAF (medical,institutional,dental) Remaining Patient Liability. Situational. Required when claim has been adjudicated by payer in loop 2330B.
						sw.Write("AMT"+s
							+"EAF"+s//AMT01 1/3 Amount Qualifier Code: EAF=Amount Owed.
							+AmountToStrNoLeading(claimPatientPortionAmt));//AMT02 1/18 Monetary Amount:
						EndSegment(sw);//AMT03 Not used.
						//2320 AMT: A8 (medical,institutional,dental) COB Total Non-Covered Amount. Situational. Can be set when primary claim was not adjudicated. We do not use.
					}
					if(IsClaimConnect(clearhouse)) {
						//2320 DMG: Other subscriber demographics. This segment is not allowed in X12. ClaimConnect requires this information anyway. They will fix their validator later.
						sw.Write("DMG"+s
							+"D8"+s//DMG01 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD.
							+otherSubsc.Birthdate.ToString("yyyyMMdd")+s//DMG02 1/35 Date Time Period: Birthdate. The othet subscriber birtdate is validated.
							+GetGender(otherSubsc.Gender));//DMG03 1/1 Gender Code: F=Female, M=Male, U=Unknown.
							EndSegment(sw);
					}
					//2320 OI: (medical,institutional,dental) Other Insurance Coverage Information.
					sw.Write("OI"+s
						+s//OI01 1/2 Claim Filing Indicator Code: Not used.
						+s//OI02 2/2 Claim Submission Reason Code: Not used.
						+(otherSub.AssignBen?"Y":"N")+s//OI03 1/1 Yes/No Condition or Response Code:
						+s//OI04 1/1 Patient Signature Source Code: Not used in institutional or dental. Situational in medical, but we do not support.
						+s//OI05 1/1 Provider Agreement Code: Not used.
						+(otherSub.ReleaseInfo?"Y":"I"));//OI06 1/1 Release of Information Code:
					EndSegment(sw);
					//2320 MIA: (institutional) Inpatient Adjudication Information. Situational. We do not support.
					//2320 MOA: (medical,institutional,dental) Outpatient Adjudication Information. Situational. For reporting remark codes from ERAs. We don't support.
					#endregion 2320 Other subscriber information
					#region 2330A Other subscriber Name
					//2330A NM1: IL (medical,institutional,dental) Other Subscriber Name.
					sw.Write("NM1"+s
						+"IL"+s//NM101 2/3 Entity Identifier Code: IL=Insured or Subscriber.
						+"1"+s//NM102 1/1 Entity Type Qualifier: 1=Person.
						+Sout(otherSubsc.LName,60)+s//NM103 1/60 Name Last or Organization Name: Never blank, because validated in the patient edit window when a patient is added/edited.
						+Sout(otherSubsc.FName,35)+s//NM104 1/35 Name First:
						+Sout(otherSubsc.MiddleI,25)+s//NM105 1/25 Middle Name:
						+s//NM106 1/10 Name Prefix: Not used.
						+s//NM107 1/10 Name Suffix: Situational. No corresponding field in OD.
						+"MI"+s//NM108 1/2 Identification Code Qualifier: MI=Member Identification Number.
						+Sout(otherSub.SubscriberID,80));//NM109 2/80 Identification Code:
					EndSegment(sw);//NM110 through NM112 are not used.
					//2330A N3: Other Subscriber Address.
					sw.Write("N3"+s+Sout(otherSubsc.Address,55));//N301 1/55 Address Information:
					if(otherSubsc.Address2!="") {
						sw.Write(s+Sout(otherSubsc.Address2,55));
					}
					EndSegment(sw);//N302 1/55 Address Information:
					//2330A N4: (medical,institutional,dental) Other Subscriber City, State, Zip Code.
					sw.Write("N4"+s
						+Sout(otherSubsc.City,30)+s//N401 2/30 City Name:
						+Sout(otherSubsc.State,2,2)+s//N402 2/2 State or Province Code:
						+Sout(otherSubsc.Zip.Replace("-",""),15));//N403 3/15 Postal Code:
					EndSegment(sw);//N404 through N407 are either not required or are required when the address is outside of the United States.
					//2330A REF: (medical,institutional,dental) Other Subscriber Secondary Identification. Situational. Not supported.
					#endregion 2330A Other subscriber Name
					#region Other payer
					//2330B NM1: (medical,institutional,dental) Other Payer Name.
					sw.Write("NM1"+s
						+"PR"+s//NM101 2/3 Entity Code Identifier: PR=Payer.
						+"2"+s);//NM102 1/1 Entity Type Qualifier: 2=Non-Person.
					//NM103 1/60 Name Last or Organization Name:
					if(IsEMS(clearhouse)) {
						long employerNum=0;
						if(otherPlan!=null) {
							employerNum=otherPlan.EmployerNum;
						}
						//This is a special situation requested by EMS.  This tacks the employer onto the end of the carrier.
						sw.Write(Sout(otherCarrier.CarrierName,30)+"|"+Sout(Employers.GetName(employerNum),30)+s);
					}
					else if(IsDentiCal(clearhouse)) {
						sw.Write("DENTICAL"+s);
					}
					else {
						sw.Write(Sout(otherCarrier.CarrierName,60)+s);
					}
					sw.Write(s//NM104 1/35 Name First: Not used.
						+s//NM105 1/25 Name Middle: Not used.
						+s//NM106 1/10 Name Prefix: Not used.
						+s//NM107 1/10 Name Suffix: Not used.
						+"PI"+s);//NM108 1/2 Identification Code Qualifier: PI=Payor Identification. XV must be used after national plan ID mandated.
					sw.Write(Sout(GetCarrierElectID(otherCarrier,clearhouse),80,2));//NM109 2/80 Identification Code:
					EndSegment(sw);//NM110 through NM112 not used.
					//2230B N3: (medical,institutional,dental) Other Payer Address. Situational. We don't support.
					//2330B N4: (medical,institutional,dental) Other Payer City, State, Zip Code. Situational. We don't support.
					//2330B DTP: 573 (medical,institutional,dental) Claim Check or Remittance Date. Situational. Claim Paid date.
					if(hasAdjForOtherPlans) {
						DateTime datePaidOtherIns=DateTime.Today;
						DateTime dtThisCP;
						for(int j=0;j<claimProcs.Count;j++) {
							dtThisCP=ClaimProcs.GetDatePaid(claimProcList,claimProcs[j].ProcNum,claimProcs[j].PlanNum);
							if(dtThisCP>datePaidOtherIns) {
								datePaidOtherIns=dtThisCP;
							}
						}
						//it's a required segment, so always include it.
						sw.Write("DTP"+s
							+"573"+s//DTP01 3/3 Date/Time Qualifier: 573=Date Claim Paid.
							+"D8"+s//DTP02 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD.
							+datePaidOtherIns.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period:
						EndSegment(sw);
					}
					//2330B REF: (medical,institutional,dental) Other Payer Secondary Identifier. Situational. We do not use.
					//2330B REF: G1 (medical,institutional,dental) Other Payer Prior Authorization Number. Situational. We do not use.
					//2330B REF: 9F (medical,institutional,dental) Other Payer Referral Number. Situational. We do not use.
					//2330B REF: T4 (medical,institutional,dental) Other Payer Claim Adjustment Indicator. Situational. We do not use.
					//2330B REF: G3 (dental) Other Payer Predetermination Identification. Situational. We do not use.
					//2230B REF: F8 (medical,institutional,dental) Other Payer Claim Control Number. Situational. We do not use.					
					if(medType==EnumClaimMedType.Medical) {
						//2330C NM1: (medical) Other Payer Referring Provider. Situational. Only used in crosswalking COBs. We do not use.
						//2330C REF: (medical) Other Payer Referring Provider Secondary Identification. We do not use.
						//2330D NM1: 82 (medical) Other Payer Rendering Provider. Situational. Only used in crosswalking COBs. We do not use.
						//2330D REF: (medical) Other Payer Rendering Provider Secondary Identificaiton. We do not use.
						//2330E NM1: 77 (medical) Other Payer Service Facility Location. Situational. We do not use.
						//2330E REF: (medical) Other Payer Service Facility Location Secondary Identification. We do not use.
						//2330F NM1: DQ (medical) Other Payer Supervising Provider. Situational. We do not use.
						//2330F REF: (medical) Other Payer Supervising Provider Secondary Identificaiton. We do not use.
						//2330G NM1: 85 (medical) Other Payer Billing Provider. Situational. We do not use.
						//2330G REF: (medical) Other Payer Billing Provider Secondary Identification. We do not use.
					}
					else if(medType==EnumClaimMedType.Institutional) {
						//2330C NM1: 71 (institutional) Other Payer Attending Provider. Situational. Only used in crosswalking COBs. We do not use.
						//2330C REF: (institutional) Other Payer Attending Provider Secondary Identification. We do not use.
						//2330D NM1: 72 (institutional) Other Payer Operating Physician. Situational.
						//2330D REF: (institutional) Other Payer Operating Physician Secondary Identificaiton. We do not use.
						//2330E NM1: ZZ (institutional) Other Payer Other Operating Physician. Situational. We do not use.
						//2330E REF: (institutional) Other Payer Other Operating Physician Secondary Identificaiton. We do not use.
						//2330F NM1: 77 (institutional) Other Payer Service Facility Location. Situational. We do not use.
						//2330F REF: (institutional) Other Payer Service Facility Location Secondary Identification. We do not use.
						//2330G NM1: 82 (institutional) Other Payer Rendering Provider Name. Situatiuonal. We do not use.
						//2330G REF: (institutional) Other Payer Rendering Provider Secondary Identificaiton. We do not use.
						//2330H NM1: DN (institutional) Other Payer Referring Provider. Situational. We do not use.
						//2330H REF: (institutional) Other Payer Referring Provider Secondary Identificaiton. We do not use.
						//2330I NM1: 85 (institutional) Other Payer Billing Provider. Situational. We do not use.
						//2330I REF: (institutional) Other Payer Billing Provider Secondary Identification. We do not use.
					}
					else if(medType==EnumClaimMedType.Dental) {
						//2330C NM1: (dental) Other Payer Referring Provider. Situational. Only used in crosswalking COBs. We do not use.
						//2330C REF: (dental) Other Payer Referring Provider Secondary Identification. We do not use.
						//2330D NM1: 82 (dental) Other Payer Rendering Provider. Situational. Only used in crosswalking COBs. We do not use.
						//2330D REF: (dental) Other Payer Rendering Provider Secondary Identificaiton. We do not use.
						//2330E NM1: DQ (dental) Other Payer Supervising Provider. Situational. We do not use.
						//2330E REF: (dental) Other Payer Supervising Provider Secondary Identificaiton. We do not use.
						//2330F NM1: 85 (dental) Other Payer Billing Provider. Situational. We do not use.
						//2330F REF: (dental) Other Payer Billing Provider Secondary Identification. We do not use.
						//2330G NM1: 77 (dental) Other Payer Service Facility Location. Situational. We do not use.
						//2330G REF: (dental) Other Payer Service Facility Location Secondary Identification. We do not use.
						//2330H NM1: DD (dental) Other Payer Assistant Sugeon. Situational. We do not use.
						//2330H REF: (dental) Other Payer Assistant Surgeon Secondary Identifier. We do not use.
					}
					#endregion Other payer
				}
				for(int j=0;j<claimProcs.Count;j++) {
					#region Service Line
					proc=Procedures.GetProcFromList(procList,claimProcs[j].ProcNum);
					procCode=ProcedureCodes.GetProcCode(proc.CodeNum);
					//2400 LX: Service Line Number.
					sw.Write("LX"+s+(j+1).ToString());//LX01 1/6 Assigned Number:
					EndSegment(sw);
					if(medType==EnumClaimMedType.Medical) {
						//2400 SV1: Professional Service.
						sw.Write("SV1"+s
							//SV101 Composite Medical Procedure Identifier
							+"HC"+isa16//SV101-1 2/2 Product/Service ID Qualifier: HC=Health Care.
							+Sout(claimProcs[j].CodeSent));//SV101-2 1/48 Product/Service ID: Procedure code. The rest of SV101 is not supported.
						if(proc.CodeMod1!="" || proc.CodeMod2!="" || proc.CodeMod3!="" || proc.CodeMod4!="" || proc.ClaimNote!="") {
							sw.Write(isa16+Sout(proc.CodeMod1));//SV101-3 2/2 Procedure Modifier: Situational.
						}
						if(proc.CodeMod2!="" || proc.CodeMod3!="" || proc.CodeMod4!="" || proc.ClaimNote!="") {
							sw.Write(isa16+Sout(proc.CodeMod2));//SV101-4 2/2 Procedure Modifier: Situational.
						}
						if(proc.CodeMod3!="" || proc.CodeMod4!="" || proc.ClaimNote!="") {
							sw.Write(isa16+Sout(proc.CodeMod3));//SV101-5 2/2 Procedure Modifier: Situational.
						}
						if(proc.CodeMod4!="" || proc.ClaimNote!="") {
							sw.Write(isa16+Sout(proc.CodeMod4));//SV101-6 2/2 Procedure Modifier: Situational.
						}
						if(proc.ClaimNote!="") {
							sw.Write(isa16+Sout(proc.ClaimNote,80));//SV101-7 1/80 Description: Situational.
						}
						sw.Write(s//SV101-8 is not used.
							+claimProcs[j].FeeBilled.ToString()+s);//SV102 1/18 Monetary Amount: Charge Amt.
						if(proc.UnitQtyType==ProcUnitQtyType.MinutesAnesth) {
							sw.Write("MJ"+s);//SV103 2/2 Unit or Basis for Measurement Code: MJ=minutes, UN=Unit.
						}
						else {
							sw.Write("UN"+s);//SV103 2/2 Unit or Basis for Measurement Code: MJ=minutes, UN=Unit.
						}
						sw.Write(proc.UnitQty+s);//SV104 1/15 Quantity: Service Unit Count or Anesthesia Minutes.
						if(proc.PlaceService!=claim.PlaceService) {
							sw.Write(GetPlaceService(proc.PlaceService));
						}
						sw.Write(s//SV105 1/2 Facility Code Value: Place of Service Code if different from claim.
							+s);//SV106 1/2 Service Type Code: Not used.
						//SV107: Composite Diagnosis Code Pointer. Required when 2300HI(Health Care Diagnosis Code) is used (always).
						//SV107-1: Primary diagnosis. Only allowed pointers 1-8 even though 2300HI supports 12 diagnoses.
						//We don't validate that there are not more than 8 diagnoses on one claim.
						//If the diagnosis we need is not in the first 8, then we will use the primary.
						if(proc.DiagnosticCode=="") {//If the diagnosis is blank, we will use the primary.
							sw.Write("1");//use primary.
						}
						else {
							int diagI=1;
							for(int d=0;d<diagnosisList.Count;d++) {
								if(d>7) {//we can't point to any except first 8.
									continue;
								}
								if((string)diagnosisList[d]==proc.DiagnosticCode) {
									diagI=d+1;
								}
							}
							sw.Write(diagI.ToString());
						}
						//SV107-2 through SV107-4: Other diagnoses, which we don't support yet.
						EndSegment(sw);//SV108 through SV121 are not used or situational. We do not use.
					}
					else if(medType==EnumClaimMedType.Institutional) {
						//2400 SV2: Institutional Service Line.
						sw.Write("SV2"+s
							+Sout(proc.RevCode,48)+s//SV201 1/48 Product/Service ID: Revenue Code, validated.
							//SV202 Composite Medical Procedure Identifier
							+"HC"+isa16//SV202-1 2/2 Product/Service ID Qualifier: HC=Health Care. Includes CPT codes.
							+Sout(claimProcs[j].CodeSent));//SV202-2 1/48 Product/Service ID: Procedure code. 
						//mods validated to be exactly 2 char long or else blank.
						if(proc.CodeMod1!="" || proc.CodeMod2!="" || proc.CodeMod3!="" || proc.CodeMod4!="" || proc.ClaimNote!="") {
							sw.Write(isa16+Sout(proc.CodeMod1));//SV202-3 2/2 Procedure Modifier: Situational.
						}
						if(proc.CodeMod2!="" || proc.CodeMod3!="" || proc.CodeMod4!="" || proc.ClaimNote!="") {
							sw.Write(isa16+Sout(proc.CodeMod2));//SV202-4 2/2 Procedure Modifier: Situational.
						}
						if(proc.CodeMod3!="" || proc.CodeMod4!="" || proc.ClaimNote!="") {
							sw.Write(isa16+Sout(proc.CodeMod3));//SV202-5 2/2 Procedure Modifier: Situational.
						}
						if(proc.CodeMod4!="" || proc.ClaimNote!="") {
							sw.Write(isa16+Sout(proc.CodeMod4));//SV202-6 2/2 Procedure Modifier: Situational.
						}
						if(proc.ClaimNote!="") {
							sw.Write(isa16+Sout(proc.ClaimNote,80));//SV202-7 1/80 Description: Situational.
						}
						sw.Write(s//SV202-8 is not used.
							+claimProcs[j].FeeBilled.ToString()+s);//SV203 1/18 Monetary Amount: Charge Amt.
						if(proc.UnitQtyType==ProcUnitQtyType.Days) {
							sw.Write("DA"+s);//SV204 2/2 Unit or Basis for Measurement Code: DA=Days, UN=Unit.
						}
						else {
							sw.Write("UN"+s);//SV204 2/2 Unit or Basis for Measurement Code: DA=Days, UN=Unit.
						}
						sw.Write(proc.UnitQty.ToString());//SV205 1/15 Quantity:
						EndSegment(sw);//SV206,208,209 and 210 are not used, SV207 is situational but we do not use.
					}
					else if(medType==EnumClaimMedType.Dental) {
						//2400 SV3: Dental Service.
						sw.Write("SV3"+s
								+"AD"+isa16//SV301-1 2/2 Product/Service ID Qualifier: AD=American Dental Association Codes
								+Sout(claimProcs[j].CodeSent,5));//SV301-2 1/48 Product/Service ID: Procedure code
						if(proc.ClaimNote!="") {
							sw.Write(isa16//SV301-3 2/2 Procedure Modifier: Situational. We do not use.
								+isa16//SV301-4 2/2 Procedure Modifier: Situational. We do not use.
								+isa16//SV301-5 2/2 Procedure Modifier: Situational. We do not use.
								+isa16//SV301-6 2/2 Procedure Modifier: Situational. We do not use.
								+isa16+Sout(proc.ClaimNote,80));//SV301-7 1/80 Description: Situational.
						}
						sw.Write(s//SV301-8 is not used.
							+claimProcs[j].FeeBilled.ToString());//SV302 1/18 Monetary Amount: Charge Amount.
						string placeService="";
						if(proc.PlaceService!=claim.PlaceService) {
							placeService=GetPlaceService(proc.PlaceService);
						}
						string area=GetArea(proc,procCode);
						int unitQty=Math.Max(proc.UnitQty,1);//Minimum of 1
						bool includeUnits=false;
						if(unitQty>=2) {//Standard behavior based on the X12 guide.
							includeUnits=true;
						}
						//The following carriers always want to see the unit quantity, even if it is only 1.
						if(IsColoradoMedicaid(clearhouse) || IsWashingtonMedicaid(clearhouse,carrier)) {
							includeUnits=true;
						}
						if(placeService!="" || area!="" || proc.Prosthesis!="" || includeUnits) {
							sw.Write(s+placeService);//SV303 1/2 Facility Code Value: Location Code if different from claim.
						}
						if(area!="" || proc.Prosthesis!="" || includeUnits) {
							sw.Write(s+area);//SV304 Oral Cavity Designation: SV304-1 1/3 Oral Cavity Designation Code: Area. SV304-2 through SV304-5 are situational and we do not use.
						}
						if(proc.Prosthesis!="" || includeUnits) {
							sw.Write(s+proc.Prosthesis);//SV305 1/1 Prothesis, Crown or Inlay Code: I=Initial Placement. R=Replacement.
						}
						if(includeUnits) {
							sw.Write(s+unitQty.ToString());//SV306 1/15 Quantity: Situational. Procedure count.
						}
						EndSegment(sw);//SV307 throug SV311 are either not used or are situational and we do not use.
						//2400 TOO: Tooth Information. Number/Surface. Multiple iterations of the TOO segment are allowed only when the quantity reported in Loop ID-2400 SV306 is equal to one.
						if(procCode.TreatArea==TreatmentArea.Tooth) {
							sw.Write("TOO"+s
								+"JP"+s//TOO01 1/3 Code List Qualifier Code: JP=Universal National Tooth Designation System.
								+proc.ToothNum);//TOO02 1/30 Industry Code: Tooth number.
							EndSegment(sw);//TOO03 Tooth Surface: Situational. Not applicable.
						}
						else if(procCode.TreatArea==TreatmentArea.Surf) {
							sw.Write("TOO"+s
								+"JP"+s//TOO01 1/3 Code List Qualifier Code: JP=Universal National Tooth Designation System.
								+proc.ToothNum+s);//TOO02 1/30 Industry Code: Tooth number.
							string validSurfaces=Tooth.SurfTidyForClaims(proc.Surf,proc.ToothNum);
							for(int k=0;k<validSurfaces.Length;k++) {
								if(k>0) {
									sw.Write(isa16);
								}
								sw.Write(validSurfaces.Substring(k,1));//TOO03 Tooth Surface: TOO03-1 through TOO03-5 are for individual surfaces.
							}
							EndSegment(sw);
						}
						else if(procCode.TreatArea==TreatmentArea.ToothRange) {
							string[] individTeeth=proc.ToothRange.Split(',');
							for(int t=0;t<individTeeth.Length;t++) {
								sw.Write("TOO"+s
									+"JP"+s//TOO01 1/3 Code List Qualifier Code: JP=Universal National Tooth Designation System.
									+individTeeth[t]);//TOO02 1/30 Industry Code: Tooth number.
								EndSegment(sw);//TOO03 Tooth Surface: Situational. Not applicable.
							}
						}
					}//dental
					#endregion Service Line
					//2400 PWK: (institutional) Line Supplemental Information. Situational. We do not use.
					//2400 CRC: (medical) Condition Indicator/Durable Medical Equipment. Situational. We do not use.
					#region Service DTP
					//2400 DTP: 472 (medical,institutional,dental) Service Date. Situaitonal. Required for medical. Required if different from claim for dental and inst.
					if(claim.ClaimType!="PreAuth") {
						bool useProcDateService=false;
						//Always required for medical because there is no date of service at the claim level.
						if(medType==EnumClaimMedType.Medical) {
							useProcDateService=true;
						}
						else { //Institutional and dental.
							//Standard X12 behavior, preferred by the following clearinghouses: EmdeonDental.
							//Required for institutional and dental when procedure date of service is different from the claim date of service.
							if(proc.ProcDate!=claim.DateService) {
								useProcDateService=true;
							}
						}
						//The following clearinghouses always want this segment no matter what: Apex, Inmediata.
						if(IsApex(clearhouse) || IsInmediata(clearhouse)) {
							useProcDateService=true;
						}
						if(useProcDateService) {
							sw.Write("DTP"+s
								+"472"+s//DTP01 3/3 Date/Time Qualifier: 472=Service.
								+"D8"+s//DTP02 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD.
								+proc.ProcDate.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period:
							EndSegment(sw);
						}
					}
					//2400 DTP: 139/441 (dental) Date Prior Placement. Situational. Required when replacement.
					if(proc.Prosthesis=="R") {//already validated date
						sw.Write("DTP"+s
							+"441"+s//DTP01 3/3 Date/Time Qualifier: 441=Prior Placement.
							+"D8"+s//DTP02 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD.
							+proc.DateOriginalProsth.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period:
						EndSegment(sw);
					}
					//2400 DTP: 452 (dental) Date Appliance Placement. Situational. Ortho appliance placement. We do not use.
					//2400 DTP: 446 (dental) Date Replacement. Date ortho appliance replaced. We do not use.
					//2400 DTP: 196 (medical,dental) Date Treatment Start. Situational. Rx date. We do not use.
					//2400 DTP: 198 (dental) Date Treatment Completion. Situational. We do not use.
					//2400 DTP: 471 (medical) Prescription Date: Situational. We do not use.
					//2400 DTP: 607 (medical) Date Certification Revision/Recertification. Situational. Not supported.
					//2400 DTP: 463 (medical) Date Begin Therapy. Situational. Not supported.
					//2400 DTP: 461 (medical) Date Last Certification. Situational. Not supported.
					//2400 DTP: 304 (medical) Date Last Seen. Situational. Not supported.
					//2400 DTP: 738/739 (medical) Test Date. Situational. For Dialysis. Not supported.
					//2400 DTP: 011 (medical) Date Shipped. Situational. Not supported.
					//2400 DTP: 455 (medical) Date Last X-Ray. Situational. Not supported.
					//2400 DTP: 454 (medical) Date Initial Treatment. Situational. Not supported.					
					#endregion Service DTP
					#region Service QTY MEA CN1
					//2400 QTY: PT (medical) Ambulance Patient Count. Situational. Not supported.
					//2400 QTY: FL (medical) Obstetric Anesthesia Additional Units. Situational. Anesthesia quantity. We do not use.
					//2400 MEA: (medical) Test Result. Situational. We do not use.
					//2400 CN1: (medical,dental) Contract Information. Situational. We do not use.
					#endregion Service QTY MEA CN1
					#region Service REF
					//2400 REF: G3 (dental) Service Predetermination Identification. Situational. Pretermination ID. We do not use.
					//2400 REF: G1 (medical,dental) Prior Authorization. Situational. We do not use.
					//2400 REF: 9F (medical,dental) Referral Number. Situational. We do not use.
					//2400 REF: 9A (dental) Repriced Claim Number. Situational. We do not use.
					//2400 REF: 9B (medical,institutional) Repriced Line Item Reference Number. Situational. We do not use.
					//2400 REF: 9C (dental) Adjusted Repriced claim Number. Situational. We do not use.
					//2400 REF: 9D (medical,instituitonal) Adjusted Repriced Line Item Reference Number. Situational. We do not use.
					//2400 REF: 6R (medical,institutional,dental) Line Item Control Number. ProcNum. Will later be used for ERAs.
					sw.Write("REF"+s
						+"6R"+s//REF01 2/3 Reference Identification Qualifier: 6R=Procedure Control Number.
						+proc.ProcNum.ToString());//REF02 1/50 Reference Identification: 
					EndSegment(sw);//REF03 and REF04 are not used.
					//2400 REF: EW (medical) Mammography Certification Number. Situational. We do not use.
					//2400 REF: X4 (medical) Clinical Laboratory Improvement Amendment (CLIA) Number. Situational. We do not use.
					//2400 REF: F4 (medical) Referring Clinical Laboratory Improvement Amendment (CLIA) Facility Identification. Situational. We do not use.
					//2400 REF: BT (medical) Immunization Batch Number. Situational. We do not use.
					#endregion Service REF
					#region Service AMT K3 NTE PS1 HCP LIN CTP
					//2400 AMT: T (medical,dental) Sales Tax Amount. Situational. Not supported.
					//2400 AMT: F4 (medical) Postage Claimed Amount. Situational. We do not use.
					//2400 AMT GT (institutional) Service Tax Amount. Situational. Not supported.
					//2400 AMT N8 (institutional) Facility Tax Amount. Situational. Not supported.
					//2400 K3: (medical,dental) File Information. Situational. Not supported.
					//2400 NTE: ADD/DCP (medical) Line Note. Situational. We do not use.
					//2400 NTE: TPO (medical,institutional) Third Party Organization Notes. Situational. Not sent by providers. Not supported.
					//2400 PS1: (medical) Purchased Service Information. Situational. We do not use.
					//2400 HCP: (medical,institutional,dental) Line Pricing/Repricing Information. Situational. Not used by providers. Not supported.
					#endregion Service AMT K3 NTE PS1 HCP
					#region 2410 Service Drug Identification
					//2410 LIN,CTP,REF: (medical) ?
					if(medType==EnumClaimMedType.Medical || medType==EnumClaimMedType.Institutional) {
						//2410 LIN: (medical,institutional) Drug Identification
						if(procCode.DrugNDC!="" && proc.DrugQty>0){
							sw.Write("LIN"+s+s//LIN01 1/20 Assigned Identification: Not used.
								+"N4"+s//LIN02 2/2 Product/Service ID Qualifier: N4=NDC code in 5-4-2 format, no dashes.
								+procCode.DrugNDC);//LIN03 1/48 Product/Service ID: NDC.
							EndSegment(sw);//LIN04 through LIN31 not used.
							//2410 CTP: (medical,institutional) Drug Quantity.
							sw.Write("CTP"+s+s+s+s//CTP01 through CTP03 not used.
								+proc.DrugQty.ToString()+s//CTP04 1/15 Quantity:
								+GetDrugUnitCode(proc.DrugUnit));//CTP05-1 2/2 Unit or Basis for Measurement Code: Code Qualifier, validated to not be None.
							EndSegment(sw);//CTP05-2 through CTP05-15 not used. CTP06 through CTP11 not used.
							//2410 REF (inst) Rx or compound drug association number.  Not supported.
						}
					}
					#endregion 2410 Service Drug Identification
					Provider provTreatProc=provTreat;//procedure level treating provider.
					//2410 REF: VY/XZ (medical,institutional) Prescription or Compound Drug Association Number. Situational. We do not use.
					#region 2420 Service Providers (medical)
					if(medType==EnumClaimMedType.Medical) {
						if(claim.ProvTreat!=proc.ProvNum
							&& PrefC.GetBool(PrefName.EclaimsSeparateTreatProv)) {
							//2420A NM1: 82 (medical) Rendering Provider Name. Only if different from the claim.
							provTreatProc=Providers.GetProv(proc.ProvNum);
							WriteNM1Provider("82",sw,provTreatProc);
							//2420A PRV: (medical) Rendering Provider Specialty Information.
							sw.Write("PRV"+s
								+"PE"+s//PRV01 1/3 Provider Code: PE=Performing.
								+"PXC"+s//PRV02 2/3 Reference Identification Qualifier: PXC=Health Care Provider Taxonomy Code.
								+X12Generator.GetTaxonomy(provTreatProc));//PRV03 1/50 Reference Identification: Taxonomy Code.
							EndSegment(sw);//PRV04 through PRV06 not used.
							//2420A REF: (medical) Rendering Provider Secondary Identification.
							sw.Write("REF"+s
								+"0B"+s//REF01 2/3 Reference Identification Qualifier: 0B=State License Number.
								+Sout(provTreatProc.StateLicense,50));//REF02 1/50 Reference Identification: 
							EndSegment(sw);//REF03 1/80 Description: Not used. REF04 Reference Identifier: Situational. Not used when REF01 is 0B or 1G.
						}
						//2420B NM1: Purchased Service Provider Name. Situational. We do not use.
						//2420B REF: Purchased Service Provider Secondary Identificaiton. Situational. We do not use.
						//2420C NM1: 77 (medical) Service Facility Location Name. Situational. We enforce all procs on a claim being performed at the same location so we don't need this.
						//2420C N3: (medical) Service Facility Location Address. We do not use.
						//2420C N4: (medical) Service Facility Location City, State, Zip Code. We do not use.
						//2420C REF: (medical) Service Facility Location Secondary Identification. Situational. We do not use.
						//2420D NM1: DQ (medical) Supervising Provider Name. Situational. We do not support.
						//2420D REF: (medical) Supervising Provider Secondary Identification. Situational. We do not support.
						//Emdeon Medical requires loop 2420E when the claim is sent to DMERC (Medicaid) carriers. This loop can only be used for a provider that is a person, not an organization, so we don't send this loop if not a person.
						if(!provTreatProc.IsNotPerson) { //Treating provider is a person.
							//2420E NM1: DK (medical) Ordering Provider Name. Situational. Required to be a person.
							WriteNM1Provider("DK",sw,provTreatProc);
							//2420E N3: (medical) Ordering Provider Address. Situational.
							sw.Write("N3"+s+Sout(billingAddress1,55));//N301 1/55 Address Information:
							if(billingAddress2!="") {
								sw.Write(s+Sout(billingAddress2,55));//N302 1/55 Address Information: Only required when there is a secondary address line.
							}
							EndSegment(sw);
							//2420E N4: (medical) Ordering Provider City, State, Zip Code. Situational.
							sw.Write("N4"+s
								+Sout(billingCity,30)+s//N401 2/30 City Name:
								+Sout(billingState,2,2)+s//N402 2/2 State or Provice Code:
								+Sout(billingZip.Replace("-",""),15));//N403 3/15 Postal Code:
							EndSegment(sw);//N404 through N407 are either not used or only required when outside of the United States.						
							//2420E REF: (medical) Ordering Provider Secondary Identification. Situational. Required before NPIs were in effect. We do not use this segment because we require NPI.
							//2420E PER: (medical) Ordering Provider Contact Information. Situational.
							sw.Write("PER"+s
								+"IC"+s//PER01 2/2 Contact Function Code: IC=Information Contact.
								+Sout(PrefC.GetString(PrefName.PracticeTitle),60)+s//PER02 1/60 Name: Practice Title.
								+"TE"+s);//PER03 2/2 Communication Number Qualifier: TE=Telephone.
							if(clinic==null) {
								sw.Write(Sout(PrefC.GetString(PrefName.PracticePhone),256));//PER04 1/256 Communication Number: Telephone number.
							}
							else {
								sw.Write(Sout(clinic.Phone,256));//PER04 1/256 Communication Number: Telephone number.
							}
							EndSegment(sw);//PER05 through PER08 are situational and PER09 is not used. We do not use.
						}
						//2420F NM1: (medical) Referring Provider Name. Situational. We do not use.
						//2420F REF: (medical) Referring Provider Secondary Identification. Situational. We do not use.
						//2420G NM1: PW (medical) Ambulance Pick-up Location. Situational. We do not use.
						//2420G N3: (medical) Ambulance Pick-up Location Address. We do not use.
						//2420G N4: (medical) Ambulance Pick-up Location City, State, Zip Code. We do not use.
						//2420H NM1: (medical) Ambulance Drop-off Location. Situational. We do not use.
						//2420H N3: (medical) Ambulance Drop-off Location Address. We do not use.
						//2420H N4: (medical) Ambulance Drop-off Location City, State, Zip Code. We do not use.
					}
					#endregion 2420 Service Providers (medical)
					#region 2420 Service Providers (inst)
					if(medType==EnumClaimMedType.Institutional) {
						//2420A NM1: 72 (institutional) Operating Physician Name. Situational. Only for surgical procedures. We don't support.
						//2420A REF: (instititional) Operating Physician Secondary Identification. Situational. Only for surgical procedures. We don't support.						
						//2420B NM1: ZZ (institutional) Other Operating Physician Name. Situational. We don't support.
						//2420B REF: (institutional) Other Operating Physician Secondary Identification. Situational. We don't support.
						if(claim.ProvTreat!=proc.ProvNum
							&& PrefC.GetBool(PrefName.EclaimsSeparateTreatProv)) 
						{
							provTreatProc=Providers.GetProv(proc.ProvNum);
							//2420C NM1: 82 (institutional) Rendering Provider Name. Situational. Only if different than claim attending (treating) prov. Person only, non-person not allowed.
							WriteNM1Provider("82",sw,provTreatProc.FName,provTreatProc.MI,provTreatProc.LName,provTreatProc.NationalProvID,false);
							//2420C REF: Rendering Provider Secondary Identification. Situational.
							sw.Write("REF"+s
								+"0B"+s//REF01 2/3 Reference Identification Qualifier: 0B=State License Number.
								+Sout(provTreatProc.StateLicense,50));//REF02 1/50 Reference Identification: Valided to be present.
							EndSegment(sw);//REF03 through REF04 are not used or situational.
						}
						//2420D NM1: DN (institutional) Referring Provider Name. Situational. We do not use.
						//2420D REF: (institutional) Referring Provider Secondary Identification. Situational. We do not use.
					}
					#endregion 2420 Service Providers (inst)
					#region 2420 Service Providers (dental)
					if(medType==EnumClaimMedType.Dental) {
						if(claim.ProvTreat!=proc.ProvNum
							&& PrefC.GetBool(PrefName.EclaimsSeparateTreatProv)) 
						{
							//2420A NM1: 82 (dental) Rendering Provider Name. Only if different from the claim.
							provTreatProc=Providers.GetProv(proc.ProvNum);
							WriteNM1Provider("82",sw,provTreatProc);
							//2420A PRV: (dental) Rendering Provider Specialty Information.
							sw.Write("PRV"+s
								+"PE"+s//PRV01 1/3 Provider Code: PE=Performing.
								+"PXC"+s//PRV02 2/3 Reference Identification Qualifier: PXC=Health Care Provider Taxonomy Code.
								+X12Generator.GetTaxonomy(provTreatProc));//PRV03 1/50 Reference Identification: Taxonomy Code.
							EndSegment(sw);//PRV04 through PRV06 not used.
							//2420A REF: (dental) Rendering Provider Secondary Identification. Never required because we always send NPI (validated).
							if(!IsDentiCal(clearhouse)) { //Denti-Cal never wants this.
								if(provTreatProc.StateLicense!="") {
									sw.Write("REF"+s
										+"0B"+s//REF01 2/3 Reference Identification Qualifier: 0B=State License Number.
										+Sout(provTreatProc.StateLicense,50));//REF02 1/50 Reference Identification: 
									EndSegment(sw);//REF03 1/80 Description: Not used. REF04 Reference Identifier: Situational. Not used when REF01 is 0B or 1G.
								}
							}
						}
						//2420B NM1: DD (dental) Assistant Surgeon Name. Situational. We do not support.
						//2420B PRV: AS (dental) Assistant Surgeon Specialty Information. Situational. We do not support.
						//2420B REF: (dental) Assistant Surgeon Secondary Identification. Situational. We do not support.
						//2420C NM1: DQ (dental) Supervising Provider Name. Situational. We do not support.
						//2420C REF: (dental) Supervising Provider Secondary Identification. Situational. We do not support.
						//2420D NM1: 77 (dental) Service Facility Location Name. Situational. We enforce all procs on a claim being performed at the same location so we don't need this.
						//2420D N3: (dental) Service Facility Location Address. We do not use.
						//2420D N4: (dental) Service Facility Location City, State, Zip Code. We do not use.
						//2420D REF: (dental) Service Facility Location Secondary Identification. Situational. We do not use.
					}
					#endregion 2420 Service Providers (dental)
					//2430 SVD: (medical,institutional,dental) Line Adjudication Information. Situational. We do not support.   
					//2430 CAS: (medical,institutional,dental) Line Adjustment. Situational. Required when the payer identified in Loop 2330B made line level adjustments which caused the amount paid to differ from the amount originally charged.
					//These CAS segments at the procedure level should add up to their respective claim level 2320 CAS segments.
					//Claim Adjustment Reason Codes can be found on the Washington Publishing Company website at: http://www.wpc-edi.com/reference/codelists/healthcare/claim-adjustment-reason-codes/
					if(hasAdjForOtherPlans && IsApex(clearhouse)) {//This section of code might work for other clearinghouses, but has not yet been tested, and nobody else has requested this information yet.
						double procPatientPortionAmt=Math.Max(0,claimProcs[j].FeeBilled-listProcWriteoffAmts[j]-listProcDeductibleAmts[j]-listProcPaidOtherInsAmts[j]);
						if(listProcWriteoffAmts[j]>0) {
							sw.Write("CAS"+s
								+"CO"+s//CAS01 1/2 Claim Adjustment Group Code: CO=Contractual Obligations.
								+"45"+s//CAS02 1/5 Claim Adjustment Reason Code: 45=Charge exceeds fee schedule/maximum allowable or contracted/legislated fee arrangement.
								+AmountToStrNoLeading(listProcWriteoffAmts[j]));//CAS03 1/18 Monetary Amount:
							EndSegment(sw);
						}
						if(listProcDeductibleAmts[j]>0 || procPatientPortionAmt>0) {
							sw.Write("CAS"+s
								+"PR");//CAS01 1/2 Claim Adjustment Group Code: PR=Patient Responsibility.
							if(listProcDeductibleAmts[j]>0) {
								sw.Write(s//end of previous field
									+"1"+s//CAS02 1/5 Claim Adjustment Reason Code: 1=Deductible.
									+AmountToStrNoLeading(listProcDeductibleAmts[j])+s//CAS03 1/18 Monetary Amount:
									+"1");//CAS04 1/15 Quantity:
							}
							if(procPatientPortionAmt>0) {
								sw.Write(s//end of previous field
									+"3"+s//CAS02 or CAS05 1/5 Claim Adjustment Reason Code: 3=Co-payment Amount.
									+AmountToStrNoLeading(procPatientPortionAmt));//CAS03 or CAS06 1/18 Monetary Amount:
							}
							EndSegment(sw);
						}
					}
					//2430 DTP: (medical,institutional,dental) Line Check or Remittance Date. We do not support.
					//2430 AMT: (medical,institutional,dental) Remaining Patient Liability. We do not support.
					//2440 LQ: (medical) Form Identification Code. Situational. We do not use.
					//2440 FRM: (medical) Supporting Documentation. We do not use.
				}
			}
			#region Trailers
			//Transaction Trailer
			sw.Write("SE"+s
				+(seg+1).ToString()+s//SE01 1/10 Number of Included Segments: Total segments, including ST & SE. We add 1 for this SE segment, since the seg variable is not incremented until after this segment is written.
				+transactionNum.ToString().PadLeft(4,'0'));//SE02 4/9 Transaction Set Control Number:
			EndSegment(sw);
			//Functional Group Trailer
			sw.Write("GE"+s+transactionNum.ToString()+s//GE01 1/6 Number of Transaction Sets Included.  Always 1 for us.
				+groupControlNumber//GE02 1/9 Group Control Number: Must be identical to GS06.
				+endSegment);
			#endregion Trailers
		}
Exemplo n.º 13
0
        ///<summary>Called from Eclaims and includes multiple claims.  Returns the string that was sent.
        ///The string needs to be parsed to determine the transaction numbers used for each claim.</summary>
        public static string SendBatch(Clearinghouse clearinghouseClin, List <ClaimSendQueueItem> queueItems, int batchNum, EnumClaimMedType medType,
                                       bool isAutomatic)
        {
            //each batch is already guaranteed to be specific to one clearinghouse, one clinic, and one EnumClaimMedType
            //Clearinghouse clearhouse=ClearinghouseL.GetClearinghouse(queueItems[0].ClearinghouseNum);
            string saveFile = GetFileName(clearinghouseClin, batchNum, isAutomatic);

            if (saveFile == "")
            {
                return("");
            }
            string messageText;

            try{
                messageText = GenerateBatch(clearinghouseClin, queueItems, batchNum, medType);
            }
            catch (ODException odex) {
                MessageBox.Show(odex.Message, "x837");
                return("");
            }
            if (clearinghouseClin.IsClaimExportAllowed)
            {
                if (clearinghouseClin.CommBridge == EclaimsCommBridge.PostnTrack)
                {
                    //need to clear out all CRLF from entire file
                    messageText = messageText.Replace("\r", "");
                    messageText = messageText.Replace("\n", "");
                }
                if (ODBuild.IsWeb())
                {
                    try {
                        ODCloudClient.ExportClaim(saveFile, messageText, doOverwriteFile: clearinghouseClin.CommBridge != EclaimsCommBridge.RECS);
                    }
                    catch (ODException odEx) {
                        if (odEx.ErrorCodeAsEnum == ODException.ErrorCodes.FileExists && clearinghouseClin.CommBridge == EclaimsCommBridge.RECS)
                        {
                            MessageBox.Show(RECSFileExistsMsg, "x837");
                        }
                        else
                        {
                            MessageBox.Show(odEx.Message, "x837");
                        }
                        if (odEx.ErrorCodeAsEnum != ODException.ErrorCodes.ClaimArchiveFailed)                       //If archiving failed, we can continue with sending.
                        {
                            return("");
                        }
                    }
                    catch (Exception ex) {
                        MessageBox.Show(ex.Message, "x837");
                        return("");
                    }
                }
                else
                {
                    File.WriteAllText(saveFile, messageText, Encoding.ASCII);
                    CopyToArchive(saveFile);
                }
            }
            return(messageText);
        }
Exemplo n.º 14
0
        ///<summary>Helper method for SendBatch that generates the X837 messagetext. This method is public as it is used in ClaimConnect.cs</summary>
        public static string GenerateBatch(Clearinghouse clearinghouseClin, List <ClaimSendQueueItem> queueItems, int batchNum, EnumClaimMedType medType)
        {
            string messageText = "";

            using (MemoryStream ms = new MemoryStream()) {
                using (StreamWriter sw = new StreamWriter(ms)) {
                    if (clearinghouseClin.Eformat == ElectronicClaimFormat.x837D_4010)
                    {
                        X837_4010.GenerateMessageText(sw, clearinghouseClin, batchNum, queueItems);
                    }
                    else                      //Any of the 3 kinds of 5010
                    {
                        X837_5010.GenerateMessageText(sw, clearinghouseClin, batchNum, queueItems, medType);
                    }
                    sw.Flush();                    //Write contents of sw into ms.
                    ms.Position = 0;               //Reset position to 0, or else the StreamReader below will not read anything.
                    using (StreamReader sr = new StreamReader(ms, Encoding.ASCII)) {
                        messageText = sr.ReadToEnd();
                    }
                }
            }
            return(messageText);
        }
Exemplo n.º 15
0
        ///<summary>Supply a list of ClaimSendQueueItems. Called from FormClaimSend.  Can only send to one clearinghouse at a time.  Able to send just send one claim.  Cannot include Canadian.</summary>
        public static void SendBatch(List <ClaimSendQueueItem> queueItems, Clearinghouse clearhouse, EnumClaimMedType medType)
        {
            string messageText = "";

            if (clearhouse.Eformat == ElectronicClaimFormat.Canadian)
            {
                MsgBox.Show("Eclaims", "Cannot send Canadian claims as part of Eclaims.SendBatch.");
                return;
            }
            //get next batch number for this clearinghouse
            int batchNum = Clearinghouses.GetNextBatchNumber(clearhouse);

            //---------------------------------------------------------------------------------------
            //Create the claim file for this clearinghouse
            if (clearhouse.Eformat == ElectronicClaimFormat.x837D_4010 ||
                clearhouse.Eformat == ElectronicClaimFormat.x837D_5010_dental ||
                clearhouse.Eformat == ElectronicClaimFormat.x837_5010_med_inst)
            {
                messageText = x837Controller.SendBatch(queueItems, batchNum, clearhouse, medType);
            }
            else if (clearhouse.Eformat == ElectronicClaimFormat.Renaissance)
            {
                messageText = Renaissance.SendBatch(queueItems, batchNum);
            }
            else if (clearhouse.Eformat == ElectronicClaimFormat.Dutch)
            {
                messageText = Dutch.SendBatch(queueItems, batchNum);
            }
            else
            {
                messageText = "";      //(ElectronicClaimFormat.None does not get sent)
            }
            if (messageText == "")     //if failed to create claim file properly,
            {
                return;                //don't launch program or change claim status
            }
            //----------------------------------------------------------------------------------------
            //Launch Client Program for this clearinghouse if applicable
            if (clearhouse.CommBridge == EclaimsCommBridge.None)
            {
                AttemptLaunch(clearhouse, batchNum);
            }
            else if (clearhouse.CommBridge == EclaimsCommBridge.WebMD)
            {
                if (!WebMD.Launch(clearhouse, batchNum))
                {
                    MessageBox.Show(Lan.g("Eclaims", "Error sending."));
                    return;
                }
            }
            else if (clearhouse.CommBridge == EclaimsCommBridge.BCBSGA)
            {
                if (!BCBSGA.Launch(clearhouse, batchNum))
                {
                    MessageBox.Show(Lan.g("Eclaims", "Error sending."));
                    return;
                }
            }
            else if (clearhouse.CommBridge == EclaimsCommBridge.Renaissance)
            {
                AttemptLaunch(clearhouse, batchNum);
            }
            else if (clearhouse.CommBridge == EclaimsCommBridge.ClaimConnect)
            {
                if (!ClaimConnect.Launch(clearhouse, batchNum))
                {
                    MessageBox.Show(Lan.g("Eclaims", "Error sending."));
                    return;
                }
            }
            else if (clearhouse.CommBridge == EclaimsCommBridge.RECS)
            {
                if (!RECS.Launch(clearhouse, batchNum))
                {
                    MessageBox.Show("Claim file created, but could not launch RECS client.");
                    //continue;
                }
            }
            else if (clearhouse.CommBridge == EclaimsCommBridge.Inmediata)
            {
                if (!Inmediata.Launch(clearhouse, batchNum))
                {
                    MessageBox.Show("Claim file created, but could not launch Inmediata client.");
                    //continue;
                }
            }
            else if (clearhouse.CommBridge == EclaimsCommBridge.AOS)           // added by SPK 7/13/05
            {
                if (!AOS.Launch(clearhouse, batchNum))
                {
                    MessageBox.Show("Claim file created, but could not launch AOS Communicator.");
                    //continue;
                }
            }
            else if (clearhouse.CommBridge == EclaimsCommBridge.PostnTrack)
            {
                AttemptLaunch(clearhouse, batchNum);
            }
            else if (clearhouse.CommBridge == EclaimsCommBridge.MercuryDE)
            {
                if (!MercuryDE.Launch(clearhouse, batchNum))
                {
                    MsgBox.Show("Eclaims", "Error sending.");
                    return;
                }
            }
            else if (clearhouse.CommBridge == EclaimsCommBridge.ClaimX)
            {
                if (!ClaimX.Launch(clearhouse, batchNum))
                {
                    MessageBox.Show("Claim file created, but encountered an error while launching ClaimX Client.");
                }
            }
            else if (clearhouse.CommBridge == EclaimsCommBridge.EmdeonMedical)
            {
                if (!EmdeonMedical.Launch(clearhouse, batchNum, medType))
                {
                    MessageBox.Show(Lan.g("Eclaims", "Error sending."));
                    return;
                }
            }
            //----------------------------------------------------------------------------------------
            //finally, mark the claims sent. (only if not Canadian)
            EtransType etype = EtransType.ClaimSent;

            if (clearhouse.Eformat == ElectronicClaimFormat.Renaissance)
            {
                etype = EtransType.Claim_Ren;
            }
            if (clearhouse.Eformat != ElectronicClaimFormat.Canadian)
            {
                for (int j = 0; j < queueItems.Count; j++)
                {
                    Etrans etrans = Etranss.SetClaimSentOrPrinted(queueItems[j].ClaimNum, queueItems[j].PatNum, clearhouse.ClearinghouseNum, etype, batchNum);
                    Etranss.SetMessage(etrans.EtransNum, messageText);
                }
            }
        }
Exemplo n.º 16
0
        ///<summary>Returns the clearinghouseNum for claims for the supplied payorID.  If the payorID was not entered or if no default was set, then 0 is returned.</summary>
        public static long AutomateClearinghouseHqSelection(string payorID, EnumClaimMedType medType)
        {
            //No need to check RemotingRole; no call to db.
            //payorID can be blank.  For example, Renaissance does not require payorID.
            Clearinghouse clearinghouseHq = null;

            if (medType == EnumClaimMedType.Dental)
            {
                if (PrefC.GetLong(PrefName.ClearinghouseDefaultDent) == 0)
                {
                    return(0);
                }
                clearinghouseHq = GetClearinghouse(PrefC.GetLong(PrefName.ClearinghouseDefaultDent));
            }
            if (medType == EnumClaimMedType.Medical || medType == EnumClaimMedType.Institutional)
            {
                if (PrefC.GetLong(PrefName.ClearinghouseDefaultMed) == 0)
                {
                    //No default set, substituting emdeon medical otherwise first medical clearinghouse.
                    List <Clearinghouse> listClearingHouses = GetDeepCopy(false);
                    clearinghouseHq = listClearingHouses.FirstOrDefault(x => x.CommBridge == EclaimsCommBridge.EmdeonMedical && x.HqClearinghouseNum == x.ClearinghouseNum);
                    if (clearinghouseHq == null)
                    {
                        clearinghouseHq = listClearingHouses.FirstOrDefault(x => x.Eformat == ElectronicClaimFormat.x837_5010_med_inst && x.HqClearinghouseNum == x.ClearinghouseNum);
                    }
                    //If we can't find a clearinghouse at all, just return 0.
                    if (clearinghouseHq == null)
                    {
                        return(0);
                    }
                    return(clearinghouseHq.ClearinghouseNum);
                }
                clearinghouseHq = GetClearinghouse(PrefC.GetLong(PrefName.ClearinghouseDefaultMed));
            }
            if (clearinghouseHq == null)          //we couldn't find a default clearinghouse for that medType.  Needs to always be a default.
            {
                return(0);
            }
            Clearinghouse clearingHouseOverride = GetClearinghouseByPayorID(payorID);

            if (clearingHouseOverride != null)           //an override exists for this payorID
            {
                if (clearingHouseOverride.Eformat == ElectronicClaimFormat.x837D_4010 || clearingHouseOverride.Eformat == ElectronicClaimFormat.x837D_5010_dental ||
                    clearingHouseOverride.Eformat == ElectronicClaimFormat.Canadian || clearingHouseOverride.Eformat == ElectronicClaimFormat.Ramq)
                {                                           //all dental formats
                    if (medType == EnumClaimMedType.Dental) //med type matches
                    {
                        return(clearingHouseOverride.ClearinghouseNum);
                    }
                }
                if (clearingHouseOverride.Eformat == ElectronicClaimFormat.x837_5010_med_inst)
                {
                    if (medType == EnumClaimMedType.Medical || medType == EnumClaimMedType.Institutional)                 //med type matches
                    {
                        return(clearingHouseOverride.ClearinghouseNum);
                    }
                }
            }
            //no override, so just return the default.
            return(clearinghouseHq.ClearinghouseNum);
        }
Exemplo n.º 17
0
        ///<summary>Called from Eclaims and includes multiple claims.  Returns the string that was sent.  The string needs to be parsed to determine the transaction numbers used for each claim.</summary>
        public static string SendBatch(List <ClaimSendQueueItem> queueItems, int batchNum, Clearinghouse clearhouse, EnumClaimMedType medType)
        {
            //each batch is already guaranteed to be specific to one clearinghouse, one clinic, and one EnumClaimMedType
            //Clearinghouse clearhouse=ClearinghouseL.GetClearinghouse(queueItems[0].ClearinghouseNum);
            string saveFile = GetFileName(clearhouse, batchNum);

            if (saveFile == "")
            {
                return("");
            }
            using (StreamWriter sw = new StreamWriter(saveFile, false, Encoding.ASCII)){
                if (clearhouse.Eformat == ElectronicClaimFormat.x837D_4010)
                {
                    X837_4010.GenerateMessageText(sw, clearhouse, batchNum, queueItems);
                }
                else                  //Any of the 3 kinds of 5010
                {
                    X837_5010.GenerateMessageText(sw, clearhouse, batchNum, queueItems, medType);
                }
            }
            if (clearhouse.CommBridge == EclaimsCommBridge.PostnTrack)
            {
                //need to clear out all CRLF from entire file
                string strFile = "";
                using (StreamReader sr = new StreamReader(saveFile, Encoding.ASCII)){
                    strFile = sr.ReadToEnd();
                }
                strFile = strFile.Replace("\r", "");
                strFile = strFile.Replace("\n", "");
                using (StreamWriter sw = new StreamWriter(saveFile, false, Encoding.ASCII)){
                    sw.Write(strFile);
                }
            }
            CopyToArchive(saveFile);
            return(File.ReadAllText(saveFile));
        }