///<summary></summary> public static long Insert(Clinic clinic){ if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { clinic.ClinicNum=Meth.GetLong(MethodBase.GetCurrentMethod(),clinic); return clinic.ClinicNum; } return Crud.ClinicCrud.Insert(clinic); }
///<summary></summary> public static void Update(Clinic clinic){ if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),clinic); return; } Crud.ClinicCrud.Update(clinic); }
///<summary></summary> public FormClinicEdit(Clinic clinicCur) { // // Required for Windows Form Designer support // ClinicCur=clinicCur; InitializeComponent(); Lan.F(this); }
public static Clinic[] GetList() { bool isListNull=false; lock(_lockObj) { if(_list==null) { isListNull=true; } } if(isListNull) { RefreshCache(); } Clinic[] arrayClinics; lock(_lockObj) { arrayClinics=new Clinic[_list.Length]; for(int i=0;i<_list.Length;i++) { arrayClinics[i]=_list[i].Copy(); } } return arrayClinics; }
///<summary>Clinic passed in must not be null.</summary> public static void Clinic(Clinic clinic,StringBuilder strb) { if(clinic.Phone.Length!=10) {//1000A PER04 min length=1. //But 10 digit phone is required in 2010AA and is universally assumed Comma(strb); strb.Append("Clinic Phone"); } if(clinic.Address=="") { Comma(strb); strb.Append("Clinic Address"); } if(clinic.City.Length<2) { Comma(strb); strb.Append("Clinic City"); } if(clinic.State.Length!=2) { Comma(strb); strb.Append("Clinic State(2 char)"); } if(clinic.Zip.Length<3) { Comma(strb); strb.Append("Clinic Zip"); } }
public static string Validate(Clearinghouse clearinghouseClin, Carrier carrier, Provider billProv, Clinic clinic, InsPlan insPlan, Patient subscriber, InsSub insSub, Patient patForRequest) { StringBuilder strb = new StringBuilder(); X12Validate.ISA(clearinghouseClin, strb); X12Validate.Carrier(carrier, strb); if (carrier.ElectID.Length < 2) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Electronic ID"); } if (billProv.SSN.Length != 9) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Prov TIN 9 digits"); } X12Validate.BillProv(billProv, strb); if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { X12Validate.BillingAddress(strb); } else if (clinic == null) { X12Validate.PracticeAddress(strb); } else { X12Validate.Clinic(clinic, strb); } if (insSub.SubscriberID.Length < 2) { if (strb.Length != 0) { strb.Append(","); } strb.Append("SubscriberID"); } if (subscriber.Birthdate.Year < 1880) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Subscriber Birthdate"); } if (patForRequest.PatNum != subscriber.PatNum) //Dependent validation. { if (patForRequest.Birthdate.Year < 1880) //Dependent level validation. { if (strb.Length != 0) { strb.Append(","); } strb.Append("Dependent Birthdate"); } } ElectID eID = ElectIDs.GetID(carrier.ElectID); //Medicaid uses the patient First/Last/DOB to get benefits, not group number, so skip this validation if this is medicaid bool isMedicaid = (eID != null && eID.IsMedicaid) || carrier.CarrierName.ToLower().Contains("medicaid"); if (!isMedicaid) { if (insPlan.GroupNum == "") { if (strb.Length != 0) { strb.Append(","); } strb.Append("Group Number"); } } //Darien at Dentalxchange helped us resolve one issue where the Group Number included a dash and was failing. //The fix suggested by Darien was to only include the numbers before the dash... See task #705773 if (IsClaimConnect(clearinghouseClin) && insPlan.GroupNum.Contains("-")) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Group Number: Only include the group number prior to the '-'"); } return(strb.ToString()); }
///<summary>In progress. Probably needs a different name. Info must be validated first. ///Set dependent to the currently selected patient, compares dependent.PatNum to subscriber.PatNum to either contruct a subscriber based or dependent based benefit request.</summary> public static string GenerateMessageText(Clearinghouse clearinghouseClin, Carrier carrier, Provider billProv, Clinic clinic, InsPlan insPlan, Patient subscriber, InsSub insSub, Patient patForRequest) { bool isSubscriberRequest = (subscriber.PatNum == patForRequest.PatNum); int batchNum = Clearinghouses.GetNextBatchNumber(clearinghouseClin); string groupControlNumber = batchNum.ToString(); //Must be unique within file. We will use batchNum int transactionNum = 1; StringBuilder strb = new StringBuilder(); //Interchange Control Header strb.Append("ISA*00* *"); //ISA01,ISA02: 00 + 10 spaces if (IsEmdeonDental(clearinghouseClin)) { strb.Append("00*" + Sout(clearinghouseClin.Password, 10, 10) + "*" //ISA03,ISA04: 00 + emdeon password padded to 10 characters + clearinghouseClin.ISA05 + "*" //ISA05: Sender ID type: ZZ=mutually defined. 30=TIN. Validated + "316:" + Sout(clearinghouseClin.LoginID, 11, 11) + "*" //ISA06: Emdeon vendor number + username + clearinghouseClin.ISA07 + "*" //ISA07: Receiver ID type: ZZ=mutually defined. 30=TIN. Validated + Sout("EMDEONDENTAL", 15, 15) + "*"); //ISA08: Receiver ID. Validated to make sure length is at least 2. } else { strb.Append("00* *" //ISA03,ISA04: 00 + 10 spaces + clearinghouseClin.ISA05 + "*" //ISA05: Sender ID type: ZZ=mutually defined. 30=TIN. Validated + X12Generator.GetISA06(clearinghouseClin) + "*" //ISA06: Sender ID(TIN). Or might be TIN of Open Dental + clearinghouseClin.ISA07 + "*" //ISA07: Receiver ID type: ZZ=mutually defined. 30=TIN. Validated + Sout(clearinghouseClin.ISA08, 15, 15) + "*"); //ISA08: Receiver ID. Validated to make sure length is at least 2. } strb.AppendLine(DateTime.Today.ToString("yyMMdd") + "*" //ISA09: today's date + DateTime.Now.ToString("HHmm") + "*" //ISA10: current time + "U*00401*" //ISA11 and ISA12. //ISA13: interchange control number, right aligned: + batchNum.ToString().PadLeft(9, '0') + "*" + "0*" //ISA14: no acknowledgment requested + clearinghouseClin.ISA15 + "*" //ISA15: T=Test P=Production. Validated. + ":~"); //ISA16: use ':' //Functional Group Header if (IsEmdeonDental(clearinghouseClin)) { strb.Append("GS*HS*" //GS01: HS for 270 benefit inquiry + X12Generator.GetGS02(clearinghouseClin) + "*" //GS02: Senders Code. Sometimes Jordan Sparks. Sometimes the sending clinic. + Sout("EMDEONDENTAL", 15, 15) + "*"); //GS03: Application Receiver's Code } else { strb.Append("GS*HS*" //GS01: HS for 270 benefit inquiry + X12Generator.GetGS02(clearinghouseClin) + "*" //GS02: Senders Code. Sometimes Jordan Sparks. Sometimes the sending clinic. + Sout(clearinghouseClin.GS03, 15, 2) + "*"); //GS03: Application Receiver's Code } strb.AppendLine(DateTime.Today.ToString("yyyyMMdd") + "*" //GS04: today's date + DateTime.Now.ToString("HHmm") + "*" //GS05: current time + groupControlNumber + "*" //GS06: Group control number. Max length 9. No padding necessary. + "X*" //GS07: X + "004010X092~"); //GS08: Version //Beginning of transaction-------------------------------------------------------------------------------- int seg = 0; //count segments for the ST-SE transaction //Transaction Set Header //ST02 Transact. control #. Must be unique within ISA seg++; strb.AppendLine("ST*270*" //ST01 + transactionNum.ToString().PadLeft(4, '0') + "~"); //ST02 seg++; strb.AppendLine("BHT*0022*13*" //BHT02: 13=request + transactionNum.ToString().PadLeft(4, '0') + "*" //BHT03. Can be same as ST02 + DateTime.Now.ToString("yyyyMMdd") + "*" //BHT04: Date + DateTime.Now.ToString("HHmmss") + "~"); //BHT05: Time, BHT06: not used //HL Loops----------------------------------------------------------------------------------------------- int HLcount = 1; //2000A HL: Information Source-------------------------------------------------------------------------- seg++; strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID. Here, it's always 1. + "*" //HL02: No parent. Not used + "20*" //HL03: Heirarchical level code. 20=Information source + "1~"); //HL04: Heirarchical child code. 1=child HL present //2100A NM1 seg++; strb.AppendLine("NM1*PR*" //NM101: PR=Payer + "2*" //NM102: 2=Non person + Sout(carrier.CarrierName, 35) + "*" //NM103: Name Last. + "****" //NM104-07 not used + "PI*" //NM108: PI=PayorID + Sout(carrier.ElectID, 80, 2) + "~"); //NM109: PayorID. Validated to be at least length of 2. HLcount++; //2000B HL: Information Receiver------------------------------------------------------------------------ seg++; strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID. Here, it's always 2. + "1*" //HL02: Heirarchical parent id number. 1 in this simple message. + "21*" //HL03: Heirarchical level code. 21=Information receiver + "1~"); //HL04: Heirarchical child code. 1=child HL present seg++; //2100B NM1: Information Receiver Name strb.AppendLine("NM1*1P*" //NM101: 1P=Provider + (billProv.IsNotPerson?"2":"1") + "*" //NM102: 1=person,2=non-person + Sout(billProv.LName, 35) + "*" //NM103: Last name + Sout(billProv.FName, 25) + "*" //NM104: First name + Sout(billProv.MI, 25, 1) + "*" //NM105: Middle name + "*" //NM106: not used + "*" //NM107: Name suffix. not used + "XX*" //NM108: ID code qualifier. 24=EIN. 34=SSN, XX=NPI + Sout(billProv.NationalProvID, 80) + "~"); //NM109: ID code. NPI validated //2100B REF: Information Receiver ID if (IsEmdeonDental(clearinghouseClin) && IsDentiCalCarrier(carrier)) { string ref4aSegment = ""; Clearinghouse clearinghouseDentiCalHQ = Clearinghouses.GetFirstOrDefault(x => IsDentiCalClearinghouse(x), true); if (clearinghouseDentiCalHQ != null) { Clearinghouse clearinghouseDentiCalClin = Clearinghouses.OverrideFields(clearinghouseDentiCalHQ, clearinghouseClin.ClinicNum); if (clearinghouseDentiCalClin != null) { ref4aSegment = clearinghouseDentiCalClin.Password; } } seg++; strb.Append("REF*4A*" + ref4aSegment + "~"); } seg++; strb.Append("REF*"); if (billProv.UsingTIN) { strb.Append("TJ*"); //REF01: qualifier. TJ=Federal TIN } else //SSN { strb.Append("SY*"); //REF01: qualifier. SY=SSN } strb.AppendLine(Sout(billProv.SSN, 30) + "~"); //REF02: ID //2100B N3: Information Receiver Address seg++; if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { strb.Append("N3*" + Sout(PrefC.GetString(PrefName.PracticeBillingAddress), 55)); //N301: Address } else if (clinic == null) { strb.Append("N3*" + Sout(PrefC.GetString(PrefName.PracticeAddress), 55)); //N301: Address } else { strb.Append("N3*" + Sout(clinic.Address, 55)); //N301: Address } if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { if (PrefC.GetString(PrefName.PracticeBillingAddress2) == "") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*" + Sout(PrefC.GetString(PrefName.PracticeBillingAddress2), 55) + "~"); } } else if (clinic == null) { if (PrefC.GetString(PrefName.PracticeAddress2) == "") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*" + Sout(PrefC.GetString(PrefName.PracticeAddress2), 55) + "~"); } } else { if (clinic.Address2 == "") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*" + Sout(clinic.Address2, 55) + "~"); } } //2100B N4: Information Receiver City/State/Zip seg++; if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { strb.AppendLine("N4*" + Sout(PrefC.GetString(PrefName.PracticeBillingCity), 30) + "*" //N401: City + Sout(PrefC.GetString(PrefName.PracticeBillingST), 2) + "*" //N402: State + Sout(PrefC.GetString(PrefName.PracticeBillingZip).Replace("-", ""), 15) + "~"); //N403: Zip } else if (clinic == null) { strb.AppendLine("N4*" + Sout(PrefC.GetString(PrefName.PracticeCity), 30) + "*" //N401: City + Sout(PrefC.GetString(PrefName.PracticeST), 2) + "*" //N402: State + Sout(PrefC.GetString(PrefName.PracticeZip).Replace("-", ""), 15) + "~"); //N403: Zip } else { strb.AppendLine("N4*" + Sout(clinic.City, 30) + "*" //N401: City + Sout(clinic.State, 2) + "*" //N402: State + Sout(clinic.Zip.Replace("-", ""), 15) + "~"); //N403: Zip } //2100B PRV: Information Receiver Provider Info seg++; //PRV*PE*ZZ*1223G0001X~ strb.AppendLine("PRV*PE*" //PRV01: Provider Code. PE=Performing. There are many other choices. + "ZZ*" //PRV02: ZZ=Mutually defined = health care provider taxonomy code + X12Generator.GetTaxonomy(billProv) + "~"); //PRV03: Specialty code HLcount++; //2000C HL: Subscriber----------------------------------------------------------------------------------- seg++; strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID. Here, it's always 3. + "2*" //HL02: Heirarchical parent id number. 2 in this simple message. + "22*" //HL03: Heirarchical level code. 22=Subscriber + (isSubscriberRequest?"0~":"1~")); //HL04: Heirarchical child code. 0=no child HL present (no dependent) else 1 //2000C TRN: Subscriber Trace Number seg++; strb.AppendLine("TRN*1*" //TRN01: Trace Type Code. 1=Current Transaction Trace Numbers + "1*" //TRN02: Trace Number. We don't really have a good primary key yet. Keep it simple. Use 1. + "1" + billProv.SSN + "~"); //TRN03: Entity Identifier. First digit is 1=EIN. Next 9 digits are EIN. Length validated. //2100C NM1: Subscriber Name seg++; strb.AppendLine("NM1*IL*" //NM101: IL=Insured or Subscriber + "1*" //NM102: 1=Person + Sout(subscriber.LName, 35) + "*" //NM103: LName + Sout(subscriber.FName, 25) + "*" //NM104: FName + Sout(subscriber.MiddleI, 25) + "*" //NM105: MiddleName + "*" //NM106: not used + "*" //NM107: suffix. Not present in Open Dental yet. + "MI*" //NM108: MI=MemberID + Sout(insSub.SubscriberID.Replace("-", ""), 80) + "~"); //NM109: Subscriber ID. Validated to be L>2. //2100C REF: Subscriber Additional Information. Without this, old plans seem to be frequently returned. seg++; strb.AppendLine("REF*6P*" //REF01: 6P=GroupNumber + Sout(insPlan.GroupNum, 30) + "~"); //REF02: Supplemental ID. Validated. //2100C DMG: Subscriber Demographic Information seg++; strb.AppendLine("DMG*D8*" //DMG01: Date Time Period Qualifier. D8=CCYYMMDD + subscriber.Birthdate.ToString("yyyyMMdd") + "~"); //DMG02: Subscriber birthdate. Validated //DMG03: Gender code. Situational. F or M. Since this was left out in the example, //and since we don't want to send the wrong gender, we will not send this element. //2100C DTP: Subscriber Date. Deduced through trial and error that this is required by EHG even though not by X12 specs. seg++; strb.AppendLine("DTP*307*" //DTP01: Qualifier. 307=Eligibility + "D8*" //DTP02: Format Qualifier. + DateTime.Today.ToString("yyyyMMdd") + "~"); //DTP03: Date //2000D HL: Dependent Level Hierarchical Level if (isSubscriberRequest) { //2110C EQ: Subscriber Eligibility or Benefit Enquiry Information //X12 documentation seems to say that we can loop this 99 times to request very specific benefits. //ClaimConnect wants to see either an EQ*30 for "an eligibility request", or an EQ*35 for "a general benefits request". //The director of vendor implementation at ClaimConnect has informed us that we should send an EQ*35 to get the full set of benefits. seg++; strb.AppendLine("EQ*35~"); //Dental Care } else //Dependent based request. { HLcount++; seg++; strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID. + (HLcount - 1).ToString() + "*" //HL02: Heirarchical parent id number. + "23*" //HL03: Heirarchical level code. 23=Dependent + "0~"); //HL04: Heirarchical child code. 0=no child HL present (no dependent) //2000D TRN: Dependent Trace Number seg++; strb.AppendLine("TRN*1*" //TRN01: Trace Type Code. 1=Current Transaction Trace Numbers + "1*" //TRN02: Trace Number. We don't really have a good primary key yet. Keep it simple. Use 1. + "1" + billProv.SSN + "~"); //TRN03: Entity Identifier. First digit is 1=EIN. Next 9 digits are EIN. Length validated. //2100D NM1: Dependent Name seg++; strb.AppendLine("NM1*03*" //NM101: 03=Dependent + "1*" //NM102: 1=Person + Sout(patForRequest.LName, 35) + "*" //NM103: Name Last or Organization Name + Sout(patForRequest.FName, 25) + "*" //NM104: Name First + Sout(patForRequest.MiddleI, 25) + "~"); //NM105: Name Middle //2100D REF: Dependent Additional Identification seg++; strb.AppendLine("REF*6P*" //REF01: 6P=GroupNumber + Sout(insPlan.GroupNum, 30) + "~"); //REF02: Supplemental ID. Validated. //2100D DMG: Dependent Demographic Information seg++; strb.AppendLine("DMG*D8*" //DMG01: Date Time Period Qualifier. D8=CCYYMMDD + patForRequest.Birthdate.ToString("yyyyMMdd") + "~"); //DMG02: Dependent birthdate. Validated //DMG03: Gender code. Situational. F or M. Since this was left out in the example, //and since we don't want to send the wrong gender, we will not send this element. //2100D DTP: DEPENDENT Date. Deduced through trial and error that this is required by EHG even though not by X12 specs. seg++; strb.AppendLine("DTP*307*" //DTP01: Qualifier. 307=Eligibility + "D8*" //DTP02: Format Qualifier. + DateTime.Today.ToString("yyyyMMdd") + "~"); //DTP03: Date seg++; strb.AppendLine("EQ*35~"); //Dental Care } //Transaction Trailer seg++; strb.AppendLine("SE*" + seg.ToString() + "*" //SE01: Total segments, including ST & SE + transactionNum.ToString().PadLeft(4, '0') + "~"); //End of transaction-------------------------------------------------------------------------------------- //Functional Group Trailer strb.AppendLine("GE*" + transactionNum.ToString() + "*" //GE01: Number of transaction sets included + groupControlNumber + "~"); //GE02: Group Control number. Must be identical to GS06 //Interchange Control Trailer strb.AppendLine("IEA*1*" //IEA01: number of functional groups + batchNum.ToString().PadLeft(9, '0') + "~"); //IEA02: Interchange control number return(strb.ToString()); /* * return @" * ISA*00* *00* *30*AA0989922 *30*330989922 *030519*1608*U*00401*000012145*1*T*:~ * GS*HS*AA0989922*330989922*20030519*1608*12145*X*004010X092~ * ST*270*0001~ * BHT*0022*13*ASX012145WEB*20030519*1608~ * HL*1**20*1~ * NM1*PR*2*Metlife*****PI*65978~ * HL*2*1*21*1~ * NM1*1P*1*PROVLAST*PROVFIRST****XX*1234567893~ * REF*TJ*200384584~ * N3*JUNIT ROAD~ * N4*CHICAGO*IL*60602~ * PRV*PE*ZZ*1223G0001X~ * HL*3*2*22*0~ * TRN*1*12145*1AA0989922~ * NM1*IL*1*SUBLASTNAME*SUBFIRSTNAME****MI*123456789~ * DMG*D8*19750323~ * DTP*307*D8*20030519~ * EQ*30~ * SE*17*0001~ * GE*1*12145~ * IEA*1*000012145~"; */ //return "ISA*00* *00* *30*AA0989922 *30*330989922 *030519*1608*U*00401*000012145*1*T*:~GS*HS*AA0989922*330989922*20030519*1608*12145*X*004010X092~ST*270*0001~BHT*0022*13*ASX012145WEB*20030519*1608~HL*1**20*1~NM1*PR*2*Metlife*****PI*65978~HL*2*1*21*1~NM1*1P*1*PROVLAST*PROVFIRST****XX*1234567893~REF*TJ*200384584~N3*JUNIT ROAD~N4*CHICAGO*IL*60602~PRV*PE*ZZ*1223G0001X~HL*3*2*22*0~TRN*1*12145*1AA0989922~NM1*IL*1*SUBLASTNAME*SUBFIRSTNAME****MI*123456789~DMG*D8*19750323~DTP*307*D8*20030519~EQ*30~SE*17*0001~GE*1*12145~IEA*1*000012145~"; }
///<summary>Checks dependencies first. Throws exception if can't delete.</summary> public static void Delete(Clinic clinic) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), clinic); return; } //Check FK dependencies. #region Patients string command = "SELECT LName,FName FROM patient WHERE ClinicNum =" + POut.Long(clinic.ClinicNum); DataTable table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; if (i == 15) { pats += Lans.g("Clinics", "And") + " " + (table.Rows.Count - i) + " " + Lans.g("Clinics", "others"); break; } pats += table.Rows[i]["LName"].ToString() + ", " + table.Rows[i]["FName"].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because it is in use by the following patients:") + pats); } #endregion #region Payments command = "SELECT patient.LName,patient.FName FROM patient,payment " + "WHERE payment.ClinicNum =" + POut.Long(clinic.ClinicNum) + " AND patient.PatNum=payment.PatNum"; table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; if (i == 15) { pats += Lans.g("Clinics", "And") + " " + (table.Rows.Count - i) + " " + Lans.g("Clinics", "others"); break; } pats += table.Rows[i]["LName"].ToString() + ", " + table.Rows[i]["FName"].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following patients have payments using it:") + pats); } #endregion #region ClaimPayments command = "SELECT patient.LName,patient.FName FROM patient,claimproc,claimpayment " + "WHERE claimpayment.ClinicNum =" + POut.Long(clinic.ClinicNum) + " AND patient.PatNum=claimproc.PatNum" + " AND claimproc.ClaimPaymentNum=claimpayment.ClaimPaymentNum " + "GROUP BY patient.LName,patient.FName,claimpayment.ClaimPaymentNum"; table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; if (i == 15) { pats += Lans.g("Clinics", "And") + " " + (table.Rows.Count - i) + " " + Lans.g("Clinics", "others"); break; } pats += table.Rows[i]["LName"].ToString() + ", " + table.Rows[i]["FName"].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following patients have claim payments using it:") + pats); } #endregion #region Appointments command = "SELECT patient.LName,patient.FName FROM patient,appointment " + "WHERE appointment.ClinicNum =" + POut.Long(clinic.ClinicNum) + " AND patient.PatNum=appointment.PatNum"; table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; if (i == 15) { pats += Lans.g("Clinics", "And") + " " + (table.Rows.Count - i) + " " + Lans.g("Clinics", "others"); break; } pats += table.Rows[i]["LName"].ToString() + ", " + table.Rows[i]["FName"].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following patients have appointments using it:") + pats); } #endregion #region Procedures //reassign procedure.ClinicNum=0 if the procs are status D. command = "SELECT ProcNum FROM procedurelog WHERE ProcStatus=" + POut.Int((int)ProcStat.D) + " AND ClinicNum=" + POut.Long(clinic.ClinicNum); List <long> listProcNums = Db.GetListLong(command); if (listProcNums.Count > 0) { command = "UPDATE procedurelog SET ClinicNum=0 WHERE ProcNum IN (" + string.Join(",", listProcNums.Select(x => POut.Long(x))) + ")"; Db.NonQ(command); } command = "SELECT patient.LName,patient.FName FROM patient,procedurelog " + "WHERE procedurelog.ClinicNum =" + POut.Long(clinic.ClinicNum) + " AND patient.PatNum=procedurelog.PatNum"; table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; if (i == 15) { pats += Lans.g("Clinics", "And") + " " + (table.Rows.Count - i) + " " + Lans.g("Clinics", "others"); break; } pats += table.Rows[i]["LName"].ToString() + ", " + table.Rows[i]["FName"].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following patients have procedures using it:") + pats); } #endregion #region Operatories command = "SELECT OpName FROM operatory " + "WHERE ClinicNum =" + POut.Long(clinic.ClinicNum); table = Db.GetTable(command); if (table.Rows.Count > 0) { string ops = ""; for (int i = 0; i < table.Rows.Count; i++) { ops += "\r"; if (i == 15) { ops += Lans.g("Clinics", "And") + " " + (table.Rows.Count - i) + " " + Lans.g("Clinics", "others"); break; } ops += table.Rows[i]["OpName"].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following operatories are using it:") + ops); } #endregion #region Userod command = "SELECT UserName FROM userod " + "WHERE ClinicNum =" + POut.Long(clinic.ClinicNum); table = Db.GetTable(command); if (table.Rows.Count > 0) { string userNames = ""; for (int i = 0; i < table.Rows.Count; i++) { userNames += "\r"; if (i == 15) { userNames += Lans.g("Clinics", "And") + " " + (table.Rows.Count - i) + " " + Lans.g("Clinics", "others"); break; } userNames += table.Rows[i]["UserName"].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following Open Dental users are using it:") + userNames); } #endregion #region AlertSub command = "SELECT DISTINCT UserNum FROM AlertSub " + "WHERE ClinicNum =" + POut.Long(clinic.ClinicNum); table = Db.GetTable(command); if (table.Rows.Count > 0) { List <string> listUsers = new List <string>(); for (int i = 0; i < table.Rows.Count; i++) { long userNum = PIn.Long(table.Rows[i]["UserNum"].ToString()); Userod user = Userods.GetUser(userNum); if (user == null) //Should not happen. { continue; } listUsers.Add(user.UserName); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following Open Dental users are subscribed to it:") + "\r" + String.Join("\r", listUsers.OrderBy(x => x).ToArray())); } #endregion #region UserClinics command = "SELECT userod.UserName FROM userclinic INNER JOIN userod ON userclinic.UserNum=userod.UserNum " + "WHERE userclinic.ClinicNum=" + POut.Long(clinic.ClinicNum); table = Db.GetTable(command); if (table.Rows.Count > 0) { string users = ""; for (int i = 0; i < table.Rows.Count; i++) { if (i > 0) { users += ","; } users += table.Rows[i][0].ToString(); } throw new Exception( Lans.g("Clinics", "Cannot delete clinic because the following users are restricted to this clinic in security setup:") + " " + users); } #endregion //End checking for dependencies. //Clinic is not being used, OK to delete. //Delete clinic specific program properties. command = "DELETE FROM programproperty WHERE ClinicNum=" + POut.Long(clinic.ClinicNum) + " AND ClinicNum!=0"; //just in case a programming error tries to delete an invalid clinic. Db.NonQ(command); Crud.ClinicCrud.Delete(clinic.ClinicNum); }
///<summary>Only called from Chart for now. No validation is performed here. Validate before calling. There are many validtion checks, including the NPI must be exactly 10 digits.</summary> public static string BuildClickThroughXml(Provider prov, Employee emp, Patient pat) { NCScript ncScript = new NCScript(); ncScript.Credentials = new CredentialsType(); ncScript.Credentials.partnerName = NewCropPartnerName; ncScript.Credentials.name = NewCropAccountName; ncScript.Credentials.password = NewCropAccountPasssword; ncScript.Credentials.productName = NewCropProductName; ncScript.Credentials.productVersion = NewCropProductVersion; ncScript.UserRole = new UserRoleType(); if (emp == null) { ncScript.UserRole.user = UserType.LicensedPrescriber; ncScript.UserRole.role = RoleType.doctor; } else { ncScript.UserRole.user = UserType.Staff; ncScript.UserRole.role = RoleType.nurse; } ncScript.Destination = new DestinationType(); ncScript.Destination.requestedPage = RequestedPageType.compose; //This is the tab that the user will want 90% of the time. string practiceTitle = PrefC.GetString(PrefName.PracticeTitle); //May be blank. string practicePhone = PrefC.GetString(PrefName.PracticePhone); //Validated to be 10 digits within the chart. string practiceFax = PrefC.GetString(PrefName.PracticeFax); //Validated to be 10 digits within the chart. string practiceAddress = PrefC.GetString(PrefName.PracticeAddress); //Validated to exist in chart. string practiceAddress2 = PrefC.GetString(PrefName.PracticeAddress2); //May be blank. string practiceCity = PrefC.GetString(PrefName.PracticeCity); //Validated to exist in chart. string practiceState = PrefC.GetString(PrefName.PracticeST); //Validated to be a US state code in chart. string practiceZip = Regex.Replace(PrefC.GetString(PrefName.PracticeZip), "[^0-9]*", ""); //Zip with all non-numeric characters removed. Validated to be 9 digits in chart. string practiceZip4 = practiceZip.Substring(5); //Last 4 digits of zip. practiceZip = practiceZip.Substring(0, 5); //First 5 digits of zip. string country = "US"; //Always United States for now. //if(CultureInfo.CurrentCulture.Name.Length>=2) { // country=CultureInfo.CurrentCulture.Name.Substring(CultureInfo.CurrentCulture.Name.Length-2); //} ncScript.Account = new AccountTypeRx(); //Each LicensedPrescriberID must be unique within an account. Since we send ProvNum for LicensedPrescriberID, each OD database must have a unique AccountID. ncScript.Account.ID = PrefC.GetString(PrefName.NewCropAccountId); //Customer account number then a dash then a random alpha-numeric string of 3 characters, followed by 2 digits. ncScript.Account.accountName = practiceTitle; //May be blank. ncScript.Account.siteID = "1"; //Always send 1. For each AccountID/SiteID pair, a separate database will be created in NewCrop. ncScript.Account.AccountAddress = new AddressType(); ncScript.Account.AccountAddress.address1 = practiceAddress; //Validated to exist in chart. ncScript.Account.AccountAddress.address2 = practiceAddress2; //May be blank. ncScript.Account.AccountAddress.city = practiceCity; //Validated to exist in chart. ncScript.Account.AccountAddress.state = practiceState; //Validated to be a US state code in chart. ncScript.Account.AccountAddress.zip = practiceZip; //Validated to be 9 digits in chart. First 5 digits go in this field. ncScript.Account.AccountAddress.zip4 = practiceZip4; //Validated to be 9 digits in chart. Last 4 digits go in this field. ncScript.Account.AccountAddress.country = country; //Validated above. ncScript.Account.accountPrimaryPhoneNumber = practicePhone; //Validated to be 10 digits within the chart. ncScript.Account.accountPrimaryFaxNumber = practiceFax; //Validated to be 10 digits within the chart. ncScript.Location = new LocationType(); if (PrefC.GetBool(PrefName.EasyNoClinics) || pat.ClinicNum == 0) //No clinics. { ncScript.Location.ID = "0"; //Always 0, since clinicnums must be >= 1, will never overlap with a clinic if the office turns clinics on after first use. ncScript.Location.locationName = practiceTitle; //May be blank. ncScript.Location.LocationAddress = new AddressType(); ncScript.Location.LocationAddress.address1 = practiceAddress; //Validated to exist in chart. ncScript.Location.LocationAddress.address2 = practiceAddress2; //May be blank. ncScript.Location.LocationAddress.city = practiceCity; //Validated to exist in chart. ncScript.Location.LocationAddress.state = practiceState; //Validated to be a US state code in chart. ncScript.Location.LocationAddress.zip = practiceZip; //Validated to be 9 digits in chart. First 5 digits go in this field. ncScript.Location.LocationAddress.zip4 = practiceZip4; //Validated to be 9 digits in chart. Last 4 digits go in this field. ncScript.Location.LocationAddress.country = country; //Validated above. ncScript.Location.primaryPhoneNumber = practicePhone; //Validated to be 10 digits within the chart. ncScript.Location.primaryFaxNumber = practiceFax; //Validated to be 10 digits within the chart. ncScript.Location.pharmacyContactNumber = practicePhone; //Validated to be 10 digits within the chart. } else //Using clinics. { Clinic clinic = Clinics.GetClinic(pat.ClinicNum); ncScript.Location.ID = clinic.ClinicNum.ToString(); //A positive integer. ncScript.Location.locationName = clinic.Description; //May be blank. ncScript.Location.LocationAddress = new AddressType(); ncScript.Location.LocationAddress.address1 = clinic.Address; //Validated to exist in chart. ncScript.Location.LocationAddress.address2 = clinic.Address2; //May be blank. ncScript.Location.LocationAddress.city = clinic.City; //Validated to exist in chart. ncScript.Location.LocationAddress.state = clinic.State; //Validated to be a US state code in chart. string clinicZip = Regex.Replace(clinic.Zip, "[^0-9]*", ""); //Zip with all non-numeric characters removed. Validated to be 9 digits in chart. string clinicZip4 = clinicZip.Substring(5); //Last 4 digits of zip. clinicZip = clinicZip.Substring(0, 5); //First 5 digits of zip. ncScript.Location.LocationAddress.zip = clinicZip; //Validated to be 9 digits in chart. First 5 digits go in this field. ncScript.Location.LocationAddress.zip4 = clinicZip4; //Validated to be 9 digits in chart. Last 4 digits go in this field. ncScript.Location.LocationAddress.country = country; //Validated above. ncScript.Location.primaryPhoneNumber = clinic.Phone; //Validated to be 10 digits within the chart. ncScript.Location.primaryFaxNumber = clinic.Fax; //Validated to be 10 digits within the chart. ncScript.Location.pharmacyContactNumber = clinic.Phone; //Validated to be 10 digits within the chart. } ncScript.LicensedPrescriber = new LicensedPrescriberType(); //Each unique provider ID sent to NewCrop will cause a billing charge. //Some customer databases have provider duplicates, because they have one provider record per clinic with matching NPIs. //We send NPI as the ID to prevent extra NewCrop charges. //Conversation with NewCrop: //Question: If one of our customers clicks through to NewCrop with 2 different LicensedPrescriber.ID values, // but with the same provider name and NPI, will Open Dental be billed twice or just one time for the NPI used? //Answer: "They would be billed twice. The IDs you send us should always be maintained and unique. // Users are always identified by LicensedPrescriber ID, since their name or credentials could potentially change." ncScript.LicensedPrescriber.ID = prov.NationalProvID; //UPIN is obsolete ncScript.LicensedPrescriber.LicensedPrescriberName = new PersonNameType(); ncScript.LicensedPrescriber.LicensedPrescriberName.last = prov.LName.Trim(); //Cannot be blank. ncScript.LicensedPrescriber.LicensedPrescriberName.first = prov.FName.Trim(); //Cannot be blank. ncScript.LicensedPrescriber.LicensedPrescriberName.middle = prov.MI; //May be blank. ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.DDS; //There is no blank or none option, so we have to pick a default value. DDS=0, so would be default anyway. string[] suffixes = prov.Suffix.ToUpper().Split(' ', '.'); for (int i = 0; i < suffixes.Length; i++) { if (suffixes[i] == "I") { ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.I; break; } else if (suffixes[i] == "II") { ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.II; break; } else if (suffixes[i] == "III") { ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.III; break; } else if (suffixes[i] == "JR") { ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.Jr; break; } else if (suffixes[i] == "SR") { ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.Sr; break; } } if (prov.DEANum.ToLower() == "none") { ncScript.LicensedPrescriber.dea = "NONE"; } else { ncScript.LicensedPrescriber.dea = prov.DEANum; } ncScript.LicensedPrescriber.licenseState = prov.StateWhereLicensed; //Validated to be a US state code in the chart. ncScript.LicensedPrescriber.licenseNumber = prov.StateLicense; //Validated to exist in chart. ncScript.LicensedPrescriber.npi = prov.NationalProvID; //Validated to be 10 digits in chart. //ncScript.LicensedPrescriber.freeformCredentials=;//This is where DDS and DMD should go, but we don't support this yet. Probably not necessary anyway. if (emp != null) { ncScript.Staff = new StaffType(); ncScript.Staff.ID = "emp" + emp.EmployeeNum.ToString(); //A positive integer. Returned in the ExternalUserID field when retreiving prescriptions from NewCrop. Also, provider ID is returned in the same field if a provider created the prescription, so that we can create a distintion between employee IDs and provider IDs. ncScript.Staff.StaffName = new PersonNameType(); ncScript.Staff.StaffName.first = emp.FName; //First name or last name will not be blank. Validated in Chart. ncScript.Staff.StaffName.last = emp.LName; //First name or last name will not be blank. Validated in Chart. ncScript.Staff.StaffName.middle = emp.MiddleI; //May be blank. } ncScript.Patient = new PatientType(); ncScript.Patient.ID = pat.PatNum.ToString(); //A positive integer. ncScript.Patient.PatientName = new PersonNameType(); ncScript.Patient.PatientName.last = pat.LName; //Validated to exist in Patient Edit window. ncScript.Patient.PatientName.first = pat.FName; //May be blank. ncScript.Patient.PatientName.middle = pat.MiddleI; //May be blank. ncScript.Patient.medicalRecordNumber = pat.PatNum.ToString(); //A positive integer. //NewCrop specifically requested that we do not send SSN. //ncScript.Patient.socialSecurityNumber=Regex.Replace(pat.SSN,"[^0-9]*","");//Removes all non-numerical characters. ncScript.Patient.PatientAddress = new AddressOptionalType(); ncScript.Patient.PatientAddress.address1 = pat.Address; //May be blank. ncScript.Patient.PatientAddress.address2 = pat.Address2; //May be blank. ncScript.Patient.PatientAddress.city = pat.City; //May be blank. ncScript.Patient.PatientAddress.state = pat.State; //May be blank. Validated in chart to be blank or to be a valid US state code. ncScript.Patient.PatientAddress.zip = pat.Zip; //May be blank. ncScript.Patient.PatientAddress.country = country; //Validated above. ncScript.Patient.PatientContact = new ContactType(); ncScript.Patient.PatientContact.homeTelephone = pat.HmPhone; //May be blank. Does not need to be 10 digits. ncScript.Patient.PatientCharacteristics = new PatientCharacteristicsType(); ncScript.Patient.PatientCharacteristics.dob = pat.Birthdate.ToString("yyyyMMdd"); //DOB must be in CCYYMMDD format. if (pat.Gender == PatientGender.Male) { ncScript.Patient.PatientCharacteristics.gender = GenderType.M; } else if (pat.Gender == PatientGender.Female) { ncScript.Patient.PatientCharacteristics.gender = GenderType.F; } else { ncScript.Patient.PatientCharacteristics.gender = GenderType.U; } ncScript.Patient.PatientCharacteristics.genderSpecified = true; //NewCrop programmer's comments regarding other fields we are not currently using (these fields are sent back when fetching prescriptions in the Chart): //ExternalPrescriptionId = your unique identifier for the prescription, only to be used if you are generating the prescription on your own UI. // This is referenced by NewCrop, and cannot be populated with any other value. //EncounterIdentifier = unique ID for the patient visit (e.g. John Doe, 11/11/2013). // This is used by NewCrop for reporting events against a visit, but otherwise does not impact the session. //EpisodeIdentifier = unique ID for the patient’s issue (e.g. John Doe’s broken leg) which may include multiple visits. // Currently not used by NewCrop except for being echoed back; it is possible this functionality would be expanded in the future based on its intent as noted. //ExternalSource = a codified field noting the origin of the prescription. This may not be used. //Serialize MemoryStream memoryStream = new MemoryStream(); XmlSerializer xmlSerializer = new XmlSerializer(typeof(NCScript)); xmlSerializer.Serialize(memoryStream, ncScript); byte[] memoryStreamInBytes = memoryStream.ToArray(); return(Encoding.UTF8.GetString(memoryStreamInBytes, 0, memoryStreamInBytes.Length)); }
public static string Validate(Clearinghouse clearhouse,Carrier carrier,Provider billProv,Clinic clinic,InsPlan insPlan,Patient subscriber,InsSub insSub) { StringBuilder strb=new StringBuilder(); X12Validate.ISA(clearhouse,strb); X12Validate.Carrier(carrier,strb); if(carrier.ElectID.Length<2) { if(strb.Length!=0) { strb.Append(","); } strb.Append("Electronic ID"); } if(billProv.SSN.Length!=9) { if(strb.Length!=0) { strb.Append(","); } strb.Append("Prov TIN 9 digits"); } X12Validate.BillProv(billProv,strb); if(clinic==null) { X12Validate.PracticeAddress(strb); } else { X12Validate.Clinic(clinic,strb); } if(insSub.SubscriberID.Length<2) { if(strb.Length!=0) { strb.Append(","); } strb.Append("SubscriberID"); } if(subscriber.Birthdate.Year<1880) { if(strb.Length!=0) { strb.Append(","); } strb.Append("Subscriber Birthdate"); } if(insPlan.GroupNum=="") { if(strb.Length!=0) { strb.Append(","); } strb.Append("Group Number"); } return strb.ToString(); }
private void butAdd_Click(object sender, System.EventArgs e) { Clinic ClinicCur=new Clinic(); FormClinicEdit FormCE=new FormClinicEdit(ClinicCur); FormCE.IsNew=true; FormCE.ShowDialog(); FillList(); changed=true; }
///<summary>Checks dependencies first. Throws exception if can't delete.</summary> public static void Delete(Clinic clinic) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), clinic); return; } //check patients for dependencies string command = "SELECT LName,FName FROM patient WHERE ClinicNum =" + POut.Long(clinic.ClinicNum); DataTable table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; pats += table.Rows[i][0].ToString() + ", " + table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because it is in use by the following patients:") + pats); } //check payments for dependencies command = "SELECT patient.LName,patient.FName FROM patient,payment " + "WHERE payment.ClinicNum =" + POut.Long(clinic.ClinicNum) + " AND patient.PatNum=payment.PatNum"; table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; pats += table.Rows[i][0].ToString() + ", " + table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following patients have payments using it:") + pats); } //check claimpayments for dependencies command = "SELECT patient.LName,patient.FName FROM patient,claimproc,claimpayment " + "WHERE claimpayment.ClinicNum =" + POut.Long(clinic.ClinicNum) + " AND patient.PatNum=claimproc.PatNum" + " AND claimproc.ClaimPaymentNum=claimpayment.ClaimPaymentNum " + "GROUP BY patient.LName,patient.FName,claimpayment.ClaimPaymentNum"; table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; pats += table.Rows[i][0].ToString() + ", " + table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following patients have claim payments using it:") + pats); } //check appointments for dependencies command = "SELECT patient.LName,patient.FName FROM patient,appointment " + "WHERE appointment.ClinicNum =" + POut.Long(clinic.ClinicNum) + " AND patient.PatNum=appointment.PatNum"; table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; pats += table.Rows[i][0].ToString() + ", " + table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following patients have appointments using it:") + pats); } //check procedures for dependencies command = "SELECT patient.LName,patient.FName FROM patient,procedurelog " + "WHERE procedurelog.ClinicNum =" + POut.Long(clinic.ClinicNum) + " AND patient.PatNum=procedurelog.PatNum"; table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; pats += table.Rows[i][0].ToString() + ", " + table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following patients have procedures using it:") + pats); } //check operatories for dependencies command = "SELECT OpName FROM operatory " + "WHERE ClinicNum =" + POut.Long(clinic.ClinicNum); table = Db.GetTable(command); if (table.Rows.Count > 0) { string ops = ""; for (int i = 0; i < table.Rows.Count; i++) { ops += "\r"; ops += table.Rows[i][0].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following operatories are using it:") + ops); } //delete command = "DELETE FROM clinic" + " WHERE ClinicNum = " + POut.Long(clinic.ClinicNum); Db.NonQ(command); }
///<summary>Clinic passed in must not be null.</summary> public static void Clinic(Clinic clinic,StringBuilder strb) { if(clinic.Phone.Length!=10) {//1000A PER04 min length=1. //But 10 digit phone is required in 2010AA and is universally assumed Comma(strb); strb.Append("Clinic Phone"); } if(clinic.Address.Trim()=="") { Comma(strb); strb.Append("Clinic Address"); } if(clinic.City.Trim().Length<2) { Comma(strb); strb.Append("Clinic City"); } if(clinic.State.Trim().Length!=2) { Comma(strb); strb.Append("Clinic State(2 char)"); } if(!Regex.IsMatch(clinic.Zip.Trim(),"^[0-9]{5}\\-?([0-9]{4})?$")) {//#####, or #####-, or #####-####, or #########. Dashes are removed when X12 is generated. Comma(strb); strb.Append("Clinic Zip"); } }
///<summary>Only called from Chart for now. No validation is performed here. Validate before calling. There are many validtion checks, including the NPI must be exactly 10 digits.</summary> public static string BuildNewCropClickThroughXml(Provider prov, Employee emp, Patient pat) { string deaNumDefault = ProviderClinics.GetDEANum(prov.ProvNum); NCScript ncScript = new NCScript(); ncScript.Credentials = new CredentialsType(); ncScript.Credentials.partnerName = NewCrop.NewCropPartnerName; ncScript.Credentials.name = NewCrop.NewCropAccountName; ncScript.Credentials.password = NewCrop.NewCropAccountPasssword; ncScript.Credentials.productName = NewCrop.NewCropProductName; ncScript.Credentials.productVersion = NewCrop.NewCropProductVersion; ncScript.UserRole = new UserRoleType(); bool isMidlevel = false; if (emp == null) //Provider { if (prov.IsSecondary) //Mid-level provider { isMidlevel = true; //Secondary (HYG) providers go accross to NewCrop as midlevel providers for now to satisfy the Ohio prescriber requirements. //HYG providers are not normally able to click through to NewCrop because they do not have an NPI number and an NPI is required. //In the future, instead of using the IsSecondary flag as as workaround, we should instead create a new field on the provider table //or perhaps the userod table to allow the user to select the type of provider. ncScript.UserRole.user = UserType.MidlevelPrescriber; ncScript.UserRole.role = RoleType.midlevelPrescriber; } else //Fully licensed provider { ncScript.UserRole.user = UserType.LicensedPrescriber; ncScript.UserRole.role = RoleType.doctor; } } else //Employee { ncScript.UserRole.user = UserType.Staff; ncScript.UserRole.role = RoleType.nurse; } ncScript.Destination = new DestinationType(); ncScript.Destination.requestedPage = RequestedPageType.compose; //This is the tab that the user will want 90% of the time. string practiceTitle = Tidy(PrefC.GetString(PrefName.PracticeTitle), 50); //May be blank. string practicePhone = PrefC.GetString(PrefName.PracticePhone); //Validated to be 10 digits within the chart. string practiceFax = PrefC.GetString(PrefName.PracticeFax); //Validated to be 10 digits within the chart. string practiceAddress = PrefC.GetString(PrefName.PracticeAddress); //Validated to exist in chart. string practiceAddress2 = PrefC.GetString(PrefName.PracticeAddress2); //May be blank. string practiceCity = PrefC.GetString(PrefName.PracticeCity); //Validated to exist in chart. string practiceState = PrefC.GetString(PrefName.PracticeST).ToUpper(); //Validated to be a US state code in chart. string practiceZip = Regex.Replace(PrefC.GetString(PrefName.PracticeZip), "[^0-9]*", ""); //Zip with all non-numeric characters removed. Validated to be 9 digits in chart. string practiceZip4 = practiceZip.Substring(5); //Last 4 digits of zip. practiceZip = practiceZip.Substring(0, 5); //First 5 digits of zip. string country = "US"; //Always United States for now. //if(CultureInfo.CurrentCulture.Name.Length>=2) { // country=CultureInfo.CurrentCulture.Name.Substring(CultureInfo.CurrentCulture.Name.Length-2); //} ncScript.Account = new AccountTypeRx(); //Each LicensedPrescriberID must be unique within an account. Since we send ProvNum for LicensedPrescriberID, each OD database must have a unique AccountID. ncScript.Account.ID = PrefC.GetString(PrefName.NewCropAccountId); //Customer account number then a dash then a random alpha-numeric string of 3 characters, followed by 2 digits. ncScript.Account.accountName = practiceTitle; //May be blank. ncScript.Account.siteID = "1"; //Always send 1. For each AccountID/SiteID pair, a separate database will be created in NewCrop. ncScript.Account.AccountAddress = new AddressType(); ncScript.Account.AccountAddress.address1 = practiceAddress; //Validated to exist in chart. ncScript.Account.AccountAddress.address2 = practiceAddress2; //May be blank. ncScript.Account.AccountAddress.city = practiceCity; //Validated to exist in chart. ncScript.Account.AccountAddress.state = practiceState; //Validated to be a US state code in chart. ncScript.Account.AccountAddress.zip = practiceZip; //Validated to be 9 digits in chart. First 5 digits go in this field. ncScript.Account.AccountAddress.zip4 = practiceZip4; //Validated to be 9 digits in chart. Last 4 digits go in this field. ncScript.Account.AccountAddress.country = country; //Validated above. ncScript.Account.accountPrimaryPhoneNumber = practicePhone; //Validated to be 10 digits within the chart. ncScript.Account.accountPrimaryFaxNumber = practiceFax; //Validated to be 10 digits within the chart. ncScript.Location = new LocationType(); ProviderClinic provClinic = null; if (PrefC.GetBool(PrefName.EasyNoClinics) || (!PrefC.GetBool(PrefName.ElectronicRxClinicUseSelected) && pat.ClinicNum == 0) || (PrefC.GetBool(PrefName.ElectronicRxClinicUseSelected) && Clinics.ClinicNum == 0 && pat.ClinicNum == 0)) { //No clinic. ncScript.Location.ID = "0"; //Always 0, since clinicnums must be >= 1, will never overlap with a clinic if the office turns clinics on after first use. ncScript.Location.locationName = practiceTitle; //May be blank. ncScript.Location.LocationAddress = new AddressType(); ncScript.Location.LocationAddress.address1 = practiceAddress; //Validated to exist in chart. ncScript.Location.LocationAddress.address2 = practiceAddress2; //May be blank. ncScript.Location.LocationAddress.city = practiceCity; //Validated to exist in chart. ncScript.Location.LocationAddress.state = practiceState; //Validated to be a US state code in chart. ncScript.Location.LocationAddress.zip = practiceZip; //Validated to be 9 digits in chart. First 5 digits go in this field. ncScript.Location.LocationAddress.zip4 = practiceZip4; //Validated to be 9 digits in chart. Last 4 digits go in this field. ncScript.Location.LocationAddress.country = country; //Validated above. ncScript.Location.primaryPhoneNumber = practicePhone; //Validated to be 10 digits within the chart. ncScript.Location.primaryFaxNumber = practiceFax; //Validated to be 10 digits within the chart. ncScript.Location.pharmacyContactNumber = practicePhone; //Validated to be 10 digits within the chart. } else //Using clinics. { Clinic clinic = null; if (PrefC.GetBool(PrefName.ElectronicRxClinicUseSelected) && Clinics.ClinicNum != 0) { clinic = Clinics.GetClinic(Clinics.ClinicNum); } else { clinic = Clinics.GetClinic(pat.ClinicNum); } provClinic = ProviderClinics.GetOne(prov.ProvNum, clinic.ClinicNum); ncScript.Location.ID = clinic.ClinicNum.ToString(); //A positive integer. ncScript.Location.locationName = clinic.Description; //May be blank. ncScript.Location.LocationAddress = new AddressType(); ncScript.Location.LocationAddress.address1 = clinic.Address; //Validated to exist in chart. ncScript.Location.LocationAddress.address2 = clinic.Address2; //May be blank. ncScript.Location.LocationAddress.city = clinic.City; //Validated to exist in chart. ncScript.Location.LocationAddress.state = clinic.State.ToUpper(); //Validated to be a US state code in chart. string clinicZip = Regex.Replace(clinic.Zip, "[^0-9]*", ""); //Zip with all non-numeric characters removed. Validated to be 9 digits in chart. string clinicZip4 = clinicZip.Substring(5); //Last 4 digits of zip. clinicZip = clinicZip.Substring(0, 5); //First 5 digits of zip. ncScript.Location.LocationAddress.zip = clinicZip; //Validated to be 9 digits in chart. First 5 digits go in this field. ncScript.Location.LocationAddress.zip4 = clinicZip4; //Validated to be 9 digits in chart. Last 4 digits go in this field. ncScript.Location.LocationAddress.country = country; //Validated above. ncScript.Location.primaryPhoneNumber = clinic.Phone; //Validated to be 10 digits within the chart. ncScript.Location.primaryFaxNumber = clinic.Fax; //Validated to be 10 digits within the chart. ncScript.Location.pharmacyContactNumber = clinic.Phone; //Validated to be 10 digits within the chart. } //Each unique provider ID sent to NewCrop will cause a billing charge. //Some customer databases have provider duplicates, because they have one provider record per clinic with matching NPIs. //We send NPI as the ID to prevent extra NewCrop charges. //Conversation with NewCrop: //Question: If one of our customers clicks through to NewCrop with 2 different LicensedPrescriber.ID values, // but with the same provider name and NPI, will Open Dental be billed twice or just one time for the NPI used? //Answer: "They would be billed twice. The IDs you send us should always be maintained and unique. // Users are always identified by LicensedPrescriber ID, since their name or credentials could potentially change." if (isMidlevel) { ncScript.MidlevelPrescriber = new MidlevelPrescriberType(); ncScript.MidlevelPrescriber.ID = prov.NationalProvID; //UPIN is obsolete ncScript.MidlevelPrescriber.LicensedPrescriberName = NewCrop.GetPersonNameForProvider(prov); if (deaNumDefault.ToLower() == "none") { ncScript.MidlevelPrescriber.dea = "NONE"; } else { ncScript.MidlevelPrescriber.dea = deaNumDefault; } if (provClinic != null) { ncScript.MidlevelPrescriber.locationDea = provClinic.DEANum; } ncScript.MidlevelPrescriber.licenseState = prov.StateWhereLicensed.ToUpper(); //Validated to be a US state code in the chart. ncScript.MidlevelPrescriber.licenseNumber = prov.StateLicense; //Validated to exist in chart. ncScript.MidlevelPrescriber.npi = prov.NationalProvID; //Validated to be 10 digits in chart. } else //Licensed presriber { ncScript.LicensedPrescriber = new LicensedPrescriberType(); ncScript.LicensedPrescriber.ID = prov.NationalProvID; //UPIN is obsolete ncScript.LicensedPrescriber.LicensedPrescriberName = NewCrop.GetPersonNameForProvider(prov); if (deaNumDefault.ToLower() == "none") { ncScript.LicensedPrescriber.dea = "NONE"; } else { ncScript.LicensedPrescriber.dea = deaNumDefault; } if (provClinic != null) { ncScript.LicensedPrescriber.locationDea = provClinic.DEANum; } ncScript.LicensedPrescriber.licenseState = prov.StateWhereLicensed.ToUpper(); //Validated to be a US state code in the chart. ncScript.LicensedPrescriber.licenseNumber = prov.StateLicense; //Validated to exist in chart. ncScript.LicensedPrescriber.npi = prov.NationalProvID; //Validated to be 10 digits in chart. //ncScript.LicensedPrescriber.freeformCredentials=;//This is where DDS and DMD should go, but we don't support this yet. Probably not necessary anyway. } if (emp != null) { ncScript.Staff = new StaffType(); ncScript.Staff.ID = "emp" + emp.EmployeeNum.ToString(); //A positive integer. Returned in the ExternalUserID field when retreiving prescriptions from NewCrop. Also, provider ID is returned in the same field if a provider created the prescription, so that we can create a distintion between employee IDs and provider IDs. ncScript.Staff.StaffName = new PersonNameType(); ncScript.Staff.StaffName.first = emp.FName; //First name or last name will not be blank. Validated in Chart. ncScript.Staff.StaffName.last = emp.LName; //First name or last name will not be blank. Validated in Chart. ncScript.Staff.StaffName.middle = emp.MiddleI; //May be blank. } ncScript.Patient = new PatientType(); ncScript.Patient.ID = pat.PatNum.ToString(); //A positive integer. ncScript.Patient.PatientName = new PersonNameType(); ncScript.Patient.PatientName.last = pat.LName; //Validated to exist in Patient Edit window. ncScript.Patient.PatientName.first = pat.FName; //May be blank. ncScript.Patient.PatientName.middle = pat.MiddleI; //May be blank. ncScript.Patient.medicalRecordNumber = pat.PatNum.ToString(); //A positive integer. //NewCrop specifically requested that we do not send SSN. //ncScript.Patient.socialSecurityNumber=Regex.Replace(pat.SSN,"[^0-9]*","");//Removes all non-numerical characters. ncScript.Patient.PatientAddress = new AddressOptionalType(); ncScript.Patient.PatientAddress.address1 = pat.Address; //May be blank. ncScript.Patient.PatientAddress.address2 = pat.Address2; //May be blank. ncScript.Patient.PatientAddress.city = pat.City; //May be blank. ncScript.Patient.PatientAddress.state = pat.State.ToUpper(); //May be blank. Validated in chart to be blank or to be a valid US state code. //For some reason, NewCrop will fail to load if a 9 digit zip code is sent. //One customer had all 9 digit zip codes entered for their patients, so we added code here to only send the first 5 digits of the zip. //Patient zip is validated in Chart to be blank, or #####, or #####-####, or #########. if (pat.Zip == "") { ncScript.Patient.PatientAddress.zip = ""; //Blank is allowed. } else //5 or 9 digit zip. Formats are #####, or #####-####, or #########. { ncScript.Patient.PatientAddress.zip = pat.Zip.Substring(0, 5); //First 5 digts only. } ncScript.Patient.PatientAddress.country = country; //Validated above. ncScript.Patient.PatientContact = new ContactType(); //ncScript.Patient.PatientContact.backOfficeFax=;//We do not have a field to pull this information from. //ncScript.Patient.PatientContact.backOfficeTelephone=;//We do not have a field to pull this information from. ncScript.Patient.PatientContact.cellularTelephone = pat.WirelessPhone; //May be blank. Does not need to be 10 digits. ncScript.Patient.PatientContact.email = pat.Email; //May be blank, or may also contain multiple email addresses separated by commas. //ncScript.Patient.PatientContact.fax=;//We do not have a field to pull this information from. ncScript.Patient.PatientContact.homeTelephone = pat.HmPhone; //May be blank. Does not need to be 10 digits. //ncScript.Patient.PatientContact.pagerTelephone=;//We do not have a field to pull this information from. ncScript.Patient.PatientContact.workTelephone = pat.WkPhone; //May be blank. Does not need to be 10 digits. ncScript.Patient.PatientCharacteristics = new PatientCharacteristicsType(); ncScript.Patient.PatientCharacteristics.dob = pat.Birthdate.ToString("yyyyMMdd"); //DOB must be in CCYYMMDD format. if (pat.Gender == PatientGender.Male) { ncScript.Patient.PatientCharacteristics.gender = GenderType.M; } else if (pat.Gender == PatientGender.Female) { ncScript.Patient.PatientCharacteristics.gender = GenderType.F; } else { ncScript.Patient.PatientCharacteristics.gender = GenderType.U; } ncScript.Patient.PatientCharacteristics.genderSpecified = true; //NewCrop programmer's comments regarding other fields we are not currently using (these fields are sent back when fetching prescriptions in the Chart): //ExternalPrescriptionId = your unique identifier for the prescription, only to be used if you are generating the prescription on your own UI. // This is referenced by NewCrop, and cannot be populated with any other value. //EncounterIdentifier = unique ID for the patient visit (e.g. John Doe, 11/11/2013). // This is used by NewCrop for reporting events against a visit, but otherwise does not impact the session. //EpisodeIdentifier = unique ID for the patient’s issue (e.g. John Doe’s broken leg) which may include multiple visits. // Currently not used by NewCrop except for being echoed back; it is possible this functionality would be expanded in the future based on its intent as noted. //ExternalSource = a codified field noting the origin of the prescription. This may not be used. //Serialize MemoryStream memoryStream = new MemoryStream(); XmlSerializer xmlSerializer = new XmlSerializer(typeof(NCScript)); xmlSerializer.Serialize(memoryStream, ncScript); byte[] memoryStreamInBytes = memoryStream.ToArray(); return(Encoding.UTF8.GetString(memoryStreamInBytes, 0, memoryStreamInBytes.Length)); }
///<summary>Throws exception if anything about the provider information is not valid. ///All intended exceptions are Exceptions and are already translated.</summary> public static void ValidateProv(Provider prov, Clinic clinic = null) { if (prov == null) { throw new ODException(Lans.g("Erx", "Provider not found")); } ProviderClinic provClinic = ProviderClinics.GetOneOrDefault(prov.ProvNum, (clinic == null ? 0 : clinic.ClinicNum)); if (prov.IsErxEnabled == ErxEnabledStatus.Disabled) { throw new ODException(Lans.g("Erx", "Erx is disabled for provider") + ": " + prov.Abbr + ". " + Lans.g("Erx", "To enable, edit provider in Lists | Providers and acknowledge Electronic Prescription fees.")); } if (prov.IsHidden) { throw new ODException(Lans.g("Erx", "Provider") + ": " + prov.Abbr + " " + Lans.g("Erx", "is hidden") + ". " + Lans.g("Erx", "Unhide the provider to use Erx features.")); } if (prov.IsNotPerson) { throw new ODException(Lans.g("Erx", "Provider must be a person") + ": " + prov.Abbr); } string fname = prov.FName.Trim(); if (fname == "") { throw new ODException(Lans.g("Erx", "Provider first name missing") + ": " + prov.Abbr); } if (Regex.Replace(fname, "[^A-Za-z'\\- ]*", "") != fname) { throw new ODException(Lans.g("Erx", "Provider first name can only contain letters, dashes, apostrophes, or spaces.") + ": " + prov.Abbr); } string lname = prov.LName.Trim(); if (lname == "") { throw new ODException(Lans.g("Erx", "Provider last name missing") + ": " + prov.Abbr); } if (Regex.Replace(lname, "[^A-Za-z'\\- ]*", "") != lname) //Will catch situations such as "Dale Jr. III" and "Ross DMD". { throw new ODException(Lans.g("Erx", "Provider last name can only contain letters, dashes, apostrophes, or spaces. Use the suffix box for I, II, III, Jr, or Sr") + ": " + prov.Abbr); } //prov.Suffix is not validated here. In ErxXml.cs, the suffix is converted to the appropriate suffix enumeration value, or defaults to DDS if the suffix does not make sense. string deaNum = prov.DEANum; if (provClinic != null) { deaNum = provClinic.DEANum; } if (deaNum.ToLower() != "none" && !Regex.IsMatch(deaNum, "^[A-Za-z]{2}[0-9]{7}$")) { throw new ODException(Lans.g("Erx", "Provider DEA Number must be 2 letters followed by 7 digits. If no DEA Number, enter NONE.") + ": " + prov.Abbr); } string npi = Regex.Replace(prov.NationalProvID, "[^0-9]*", ""); //NPI with all non-numeric characters removed. if (npi.Length != 10) { throw new ODException(Lans.g("Erx", "Provider NPI must be exactly 10 digits") + ": " + prov.Abbr); } if (provClinic == null || provClinic.StateLicense == "") { throw new ODException(Lans.g("Erx", "Provider state license missing") + ": " + prov.Abbr); } if (provClinic == null || !USlocales.IsValidAbbr(provClinic.StateWhereLicensed)) { throw new ODException(Lans.g("Erx", "Provider state where licensed invalid") + ": " + prov.Abbr); } }
///<summary>Checks dependencies first. Throws exception if can't delete.</summary> public static void Delete(Clinic clinic) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),clinic); return; } //Check FK dependencies. #region Patients string command="SELECT LName,FName FROM patient WHERE ClinicNum =" +POut.Long(clinic.ClinicNum); DataTable table=Db.GetTable(command); if(table.Rows.Count>0) { string pats=""; for(int i=0;i<table.Rows.Count;i++) { pats+="\r"; pats+=table.Rows[i][0].ToString()+", "+table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because it is in use by the following patients:")+pats); } #endregion #region Payments command="SELECT patient.LName,patient.FName FROM patient,payment " +"WHERE payment.ClinicNum ="+POut.Long(clinic.ClinicNum) +" AND patient.PatNum=payment.PatNum"; table=Db.GetTable(command); if(table.Rows.Count>0) { string pats=""; for(int i=0;i<table.Rows.Count;i++) { pats+="\r"; pats+=table.Rows[i][0].ToString()+", "+table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because the following patients have payments using it:")+pats); } #endregion #region ClaimPayments command="SELECT patient.LName,patient.FName FROM patient,claimproc,claimpayment " +"WHERE claimpayment.ClinicNum ="+POut.Long(clinic.ClinicNum) +" AND patient.PatNum=claimproc.PatNum" +" AND claimproc.ClaimPaymentNum=claimpayment.ClaimPaymentNum " +"GROUP BY patient.LName,patient.FName,claimpayment.ClaimPaymentNum"; table=Db.GetTable(command); if(table.Rows.Count>0) { string pats=""; for(int i=0;i<table.Rows.Count;i++) { pats+="\r"; pats+=table.Rows[i][0].ToString()+", "+table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because the following patients have claim payments using it:")+pats); } #endregion #region Appointments command="SELECT patient.LName,patient.FName FROM patient,appointment " +"WHERE appointment.ClinicNum ="+POut.Long(clinic.ClinicNum) +" AND patient.PatNum=appointment.PatNum"; table=Db.GetTable(command); if(table.Rows.Count>0) { string pats=""; for(int i=0;i<table.Rows.Count;i++) { pats+="\r"; pats+=table.Rows[i][0].ToString()+", "+table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because the following patients have appointments using it:")+pats); } #endregion #region Procedures //reassign procedure.ClinicNum=0 if the procs are status D. command="UPDATE procedurelog SET ClinicNum=0 WHERE ProcStatus="+POut.Int((int)ProcStat.D); Db.NonQ(command); command="SELECT patient.LName,patient.FName FROM patient,procedurelog " +"WHERE procedurelog.ClinicNum ="+POut.Long(clinic.ClinicNum) +" AND patient.PatNum=procedurelog.PatNum"; table=Db.GetTable(command); if(table.Rows.Count>0) { string pats=""; for(int i=0;i<table.Rows.Count;i++) { pats+="\r"; pats+=table.Rows[i][0].ToString()+", "+table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because the following patients have procedures using it:")+pats); } #endregion #region Operatories command="SELECT OpName FROM operatory " +"WHERE ClinicNum ="+POut.Long(clinic.ClinicNum); table=Db.GetTable(command); if(table.Rows.Count>0) { string ops=""; for(int i=0;i<table.Rows.Count;i++) { ops+="\r"; ops+=table.Rows[i][0].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because the following operatories are using it:")+ops); } #endregion #region Userod command="SELECT UserName FROM userod " +"WHERE ClinicNum ="+POut.Long(clinic.ClinicNum); table=Db.GetTable(command); if(table.Rows.Count>0) { string userNames=""; for(int i=0;i<table.Rows.Count;i++) { userNames+="\r"; userNames+=table.Rows[i][0].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because the following Open Dental users are using it:")+userNames); } #endregion //End checking for dependencies. //Clinic is not being used, OK to delete. command= "DELETE FROM clinic" +" WHERE ClinicNum = "+POut.Long(clinic.ClinicNum); Db.NonQ(command); }
///<summary>Checks dependencies first. Throws exception if can't delete.</summary> public static void Delete(Clinic clinic) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),clinic); return; } //check patients for dependencies string command="SELECT LName,FName FROM patient WHERE ClinicNum =" +POut.Long(clinic.ClinicNum); DataTable table=Db.GetTable(command); if(table.Rows.Count>0){ string pats=""; for(int i=0;i<table.Rows.Count;i++){ pats+="\r"; pats+=table.Rows[i][0].ToString()+", "+table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because it is in use by the following patients:")+pats); } //check payments for dependencies command="SELECT patient.LName,patient.FName FROM patient,payment " +"WHERE payment.ClinicNum ="+POut.Long(clinic.ClinicNum) +" AND patient.PatNum=payment.PatNum"; table=Db.GetTable(command); if(table.Rows.Count>0){ string pats=""; for(int i=0;i<table.Rows.Count;i++){ pats+="\r"; pats+=table.Rows[i][0].ToString()+", "+table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because the following patients have payments using it:")+pats); } //check claimpayments for dependencies command="SELECT patient.LName,patient.FName FROM patient,claimproc,claimpayment " +"WHERE claimpayment.ClinicNum ="+POut.Long(clinic.ClinicNum) +" AND patient.PatNum=claimproc.PatNum" +" AND claimproc.ClaimPaymentNum=claimpayment.ClaimPaymentNum " +"GROUP BY patient.LName,patient.FName,claimpayment.ClaimPaymentNum"; table=Db.GetTable(command); if(table.Rows.Count>0){ string pats=""; for(int i=0;i<table.Rows.Count;i++){ pats+="\r"; pats+=table.Rows[i][0].ToString()+", "+table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because the following patients have claim payments using it:")+pats); } //check appointments for dependencies command="SELECT patient.LName,patient.FName FROM patient,appointment " +"WHERE appointment.ClinicNum ="+POut.Long(clinic.ClinicNum) +" AND patient.PatNum=appointment.PatNum"; table=Db.GetTable(command); if(table.Rows.Count>0){ string pats=""; for(int i=0;i<table.Rows.Count;i++){ pats+="\r"; pats+=table.Rows[i][0].ToString()+", "+table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because the following patients have appointments using it:")+pats); } //check procedures for dependencies command="SELECT patient.LName,patient.FName FROM patient,procedurelog " +"WHERE procedurelog.ClinicNum ="+POut.Long(clinic.ClinicNum) +" AND patient.PatNum=procedurelog.PatNum"; table=Db.GetTable(command); if(table.Rows.Count>0){ string pats=""; for(int i=0;i<table.Rows.Count;i++){ pats+="\r"; pats+=table.Rows[i][0].ToString()+", "+table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because the following patients have procedures using it:")+pats); } //check operatories for dependencies command="SELECT OpName FROM operatory " +"WHERE ClinicNum ="+POut.Long(clinic.ClinicNum); table=Db.GetTable(command); if(table.Rows.Count>0){ string ops=""; for(int i=0;i<table.Rows.Count;i++){ ops+="\r"; ops+=table.Rows[i][0].ToString(); } throw new Exception(Lans.g("Clinics","Cannot delete clinic because the following operatories are using it:")+ops); } //delete command= "DELETE FROM clinic" +" WHERE ClinicNum = "+POut.Long(clinic.ClinicNum); Db.NonQ(command); }
public static string Validate(Clearinghouse clearhouse, Carrier carrier, Provider billProv, Clinic clinic, InsPlan insPlan, Patient subscriber, InsSub insSub) { StringBuilder strb = new StringBuilder(); X12Validate.ISA(clearhouse, strb); X12Validate.Carrier(carrier, strb); if (carrier.ElectID.Length < 2) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Electronic ID"); } if (billProv.SSN.Length != 9) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Prov TIN 9 digits"); } X12Validate.BillProv(billProv, strb); if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { X12Validate.BillingAddress(strb); } else if (clinic == null) { X12Validate.PracticeAddress(strb); } else { X12Validate.Clinic(clinic, strb); } if (insSub.SubscriberID.Length < 2) { if (strb.Length != 0) { strb.Append(","); } strb.Append("SubscriberID"); } if (subscriber.Birthdate.Year < 1880) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Subscriber Birthdate"); } if (insPlan.GroupNum == "") { if (strb.Length != 0) { strb.Append(","); } strb.Append("Group Number"); } return(strb.ToString()); }
///<summary>In progress. Probably needs a different name. Info must be validated first.</summary> public static string GenerateMessageText(Clearinghouse clearhouse,Carrier carrier,Provider billProv,Clinic clinic,InsPlan insPlan,Patient subscriber,InsSub insSub) { int batchNum=Clearinghouses.GetNextBatchNumber(clearhouse); string groupControlNumber=batchNum.ToString();//Must be unique within file. We will use batchNum int transactionNum=1; StringBuilder strb=new StringBuilder(); //Interchange Control Header strb.AppendLine("ISA*00* *"//ISA01,ISA02: 00 + 10 spaces +"00* *"//ISA03,ISA04: 00 + 10 spaces +clearhouse.ISA05+"*"//ISA05: Sender ID type: ZZ=mutually defined. 30=TIN. Validated +X12Generator.GetISA06(clearhouse)+"*"//ISA06: Sender ID(TIN). Or might be TIN of Open Dental +clearhouse.ISA07+"*"//ISA07: Receiver ID type: ZZ=mutually defined. 30=TIN. Validated +Sout(clearhouse.ISA08,15,15)+"*"//ISA08: Receiver ID. Validated to make sure length is at least 2. +DateTime.Today.ToString("yyMMdd")+"*"//ISA09: today's date +DateTime.Now.ToString("HHmm")+"*"//ISA10: current time +"U*00401*"//ISA11 and ISA12. //ISA13: interchange control number, right aligned: +batchNum.ToString().PadLeft(9,'0')+"*" +"0*"//ISA14: no acknowledgment requested +clearhouse.ISA15+"*"//ISA15: T=Test P=Production. Validated. +":~");//ISA16: use ':' //Functional Group Header strb.AppendLine("GS*HS*"//GS01: HS for 270 benefit inquiry +X12Generator.GetGS02(clearhouse)+"*"//GS02: Senders Code. Sometimes Jordan Sparks. Sometimes the sending clinic. +Sout(clearhouse.GS03,15,2)+"*"//GS03: Application Receiver's Code +DateTime.Today.ToString("yyyyMMdd")+"*"//GS04: today's date +DateTime.Now.ToString("HHmm")+"*"//GS05: current time +groupControlNumber+"*"//GS06: Group control number. Max length 9. No padding necessary. +"X*"//GS07: X +"004010X092~");//GS08: Version //Beginning of transaction-------------------------------------------------------------------------------- int seg=0;//count segments for the ST-SE transaction //Transaction Set Header //ST02 Transact. control #. Must be unique within ISA seg++; strb.AppendLine("ST*270*"//ST01 +transactionNum.ToString().PadLeft(4,'0')+"~");//ST02 seg++; strb.AppendLine("BHT*0022*13*"//BHT02: 13=request +transactionNum.ToString().PadLeft(4,'0')+"*"//BHT03. Can be same as ST02 +DateTime.Now.ToString("yyyyMMdd")+"*"//BHT04: Date +DateTime.Now.ToString("HHmmss")+"~");//BHT05: Time, BHT06: not used //HL Loops----------------------------------------------------------------------------------------------- int HLcount=1; //2000A HL: Information Source-------------------------------------------------------------------------- seg++; strb.AppendLine("HL*"+HLcount.ToString()+"*"//HL01: Heirarchical ID. Here, it's always 1. +"*"//HL02: No parent. Not used +"20*"//HL03: Heirarchical level code. 20=Information source +"1~");//HL04: Heirarchical child code. 1=child HL present //2100A NM1 seg++; strb.AppendLine("NM1*PR*"//NM101: PR=Payer +"2*"//NM102: 2=Non person +Sout(carrier.CarrierName,35)+"*"//NM103: Name Last. +"****"//NM104-07 not used +"PI*"//NM108: PI=PayorID +Sout(carrier.ElectID,80,2)+"~");//NM109: PayorID. Validated to be at least length of 2. HLcount++; //2000B HL: Information Receiver------------------------------------------------------------------------ seg++; strb.AppendLine("HL*"+HLcount.ToString()+"*"//HL01: Heirarchical ID. Here, it's always 2. +"1*"//HL02: Heirarchical parent id number. 1 in this simple message. +"21*"//HL03: Heirarchical level code. 21=Information receiver +"1~");//HL04: Heirarchical child code. 1=child HL present seg++; //2100B NM1: Information Receiver Name strb.AppendLine("NM1*1P*"//NM101: 1P=Provider +(billProv.IsNotPerson?"2":"1")+"*"//NM102: 1=person,2=non-person +Sout(billProv.LName,35)+"*"//NM103: Last name +Sout(billProv.FName,25)+"*"//NM104: First name +Sout(billProv.MI,25,1)+"*"//NM105: Middle name +"*"//NM106: not used +"*"//NM107: Name suffix. not used +"XX*"//NM108: ID code qualifier. 24=EIN. 34=SSN, XX=NPI +Sout(billProv.NationalProvID,80)+"~");//NM109: ID code. NPI validated //2100B REF: Information Receiver ID seg++; strb.Append("REF*"); if(billProv.UsingTIN) { strb.Append("TJ*");//REF01: qualifier. TJ=Federal TIN } else {//SSN strb.Append("SY*");//REF01: qualifier. SY=SSN } strb.AppendLine(Sout(billProv.SSN,30)+"~");//REF02: ID //2100B N3: Information Receiver Address seg++; if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { strb.Append("N3*"+Sout(PrefC.GetString(PrefName.PracticeBillingAddress),55));//N301: Address } else if(clinic==null) { strb.Append("N3*"+Sout(PrefC.GetString(PrefName.PracticeAddress),55));//N301: Address } else { strb.Append("N3*"+Sout(clinic.Address,55));//N301: Address } if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { if(PrefC.GetString(PrefName.PracticeBillingAddress2)=="") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*"+Sout(PrefC.GetString(PrefName.PracticeBillingAddress2),55)+"~"); } } else if(clinic==null) { if(PrefC.GetString(PrefName.PracticeAddress2)=="") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*"+Sout(PrefC.GetString(PrefName.PracticeAddress2),55)+"~"); } } else { if(clinic.Address2=="") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*"+Sout(clinic.Address2,55)+"~"); } } //2100B N4: Information Receiver City/State/Zip seg++; if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { strb.AppendLine("N4*"+Sout(PrefC.GetString(PrefName.PracticeBillingCity),30)+"*"//N401: City +Sout(PrefC.GetString(PrefName.PracticeBillingST),2)+"*"//N402: State +Sout(PrefC.GetString(PrefName.PracticeBillingZip).Replace("-",""),15)+"~");//N403: Zip } else if(clinic==null) { strb.AppendLine("N4*"+Sout(PrefC.GetString(PrefName.PracticeCity),30)+"*"//N401: City +Sout(PrefC.GetString(PrefName.PracticeST),2)+"*"//N402: State +Sout(PrefC.GetString(PrefName.PracticeZip).Replace("-",""),15)+"~");//N403: Zip } else { strb.AppendLine("N4*"+Sout(clinic.City,30)+"*"//N401: City +Sout(clinic.State,2)+"*"//N402: State +Sout(clinic.Zip.Replace("-",""),15)+"~");//N403: Zip } //2100B PRV: Information Receiver Provider Info seg++; //PRV*PE*ZZ*1223G0001X~ strb.AppendLine("PRV*PE*"//PRV01: Provider Code. PE=Performing. There are many other choices. +"ZZ*"//PRV02: ZZ=Mutually defined = health care provider taxonomy code +X12Generator.GetTaxonomy(billProv)+"~");//PRV03: Specialty code HLcount++; //2000C HL: Subscriber----------------------------------------------------------------------------------- seg++; strb.AppendLine("HL*"+HLcount.ToString()+"*"//HL01: Heirarchical ID. Here, it's always 3. +"2*"//HL02: Heirarchical parent id number. 2 in this simple message. +"22*"//HL03: Heirarchical level code. 22=Subscriber +"0~");//HL04: Heirarchical child code. 0=no child HL present (no dependent) //2000C TRN: Subscriber Trace Number seg++; strb.AppendLine("TRN*1*"//TRN01: Trace Type Code. 1=Current Transaction Trace Numbers +"1*"//TRN02: Trace Number. We don't really have a good primary key yet. Keep it simple. Use 1. +"1"+billProv.SSN+"~");//TRN03: Entity Identifier. First digit is 1=EIN. Next 9 digits are EIN. Length validated. //2100C NM1: Subscriber Name seg++; strb.AppendLine("NM1*IL*"//NM101: IL=Insured or Subscriber +"1*"//NM102: 1=Person +Sout(subscriber.LName,35)+"*"//NM103: LName +Sout(subscriber.FName,25)+"*"//NM104: FName +Sout(subscriber.MiddleI,25)+"*"//NM105: MiddleName +"*"//NM106: not used +"*"//NM107: suffix. Not present in Open Dental yet. +"MI*"//NM108: MI=MemberID +Sout(insSub.SubscriberID.Replace("-",""),80)+"~");//NM109: Subscriber ID. Validated to be L>2. //2100C REF: Subscriber Additional Information. Without this, old plans seem to be frequently returned. seg++; strb.AppendLine("REF*6P*"//REF01: 6P=GroupNumber +Sout(insPlan.GroupNum,30)+"~");//REF02: Supplemental ID. Validated. //2100C DMG: Subscriber Demographic Information seg++; strb.AppendLine("DMG*D8*"//DMG01: Date Time Period Qualifier. D8=CCYYMMDD +subscriber.Birthdate.ToString("yyyyMMdd")+"~");//DMG02: Subscriber birthdate. Validated //DMG03: Gender code. Situational. F or M. Since this was left out in the example, //and since we don't want to send the wrong gender, we will not send this element. //2100C DTP: Subscriber Date. Deduced through trial and error that this is required by EHG even though not by X12 specs. seg++; strb.AppendLine("DTP*307*"//DTP01: Qualifier. 307=Eligibility +"D8*"//DTP02: Format Qualifier. +DateTime.Today.ToString("yyyyMMdd")+"~");//DTP03: Date //2110C EQ: Subscriber Eligibility or Benefit Enquiry Information //We can loop this 99 times to request very specific benefits. //strb.AppendLine("EQ*30~");//EQ01: 30=General Coverage seg++; strb.AppendLine("EQ*23~");//Diagnostic seg++; strb.AppendLine("EQ*4~");//Diagnostic Xray seg++; strb.AppendLine("EQ*41~");//Routine Preventive seg++; strb.AppendLine("EQ*25~");//Restorative seg++; strb.AppendLine("EQ*26~");//Endo seg++; strb.AppendLine("EQ*24~");//Perio seg++; strb.AppendLine("EQ*40~");//Oral Surgery seg++; strb.AppendLine("EQ*36~");//Crowns seg++; strb.AppendLine("EQ*39~");//Prosth seg++; strb.AppendLine("EQ*27~");//Maxillofacial Prosth seg++; strb.AppendLine("EQ*37~");//Accident seg++; strb.AppendLine("EQ*38~");//Ortho seg++; strb.AppendLine("EQ*28~");//Adjunctive // //2000D If we add a dependent loop it would go here. It would be about 20 lines. //2100D, etc //EQ series, etc. //Not allowed to send this unless subscriber and dependent are different //We would also have to add code to process the EBs which distinguishes between subscribers and dependents. // //Transaction Trailer seg++; strb.AppendLine("SE*" +seg.ToString()+"*"//SE01: Total segments, including ST & SE +transactionNum.ToString().PadLeft(4,'0')+"~"); //End of transaction-------------------------------------------------------------------------------------- //Functional Group Trailer strb.AppendLine("GE*"+transactionNum.ToString()+"*"//GE01: Number of transaction sets included +groupControlNumber+"~");//GE02: Group Control number. Must be identical to GS06 //Interchange Control Trailer strb.AppendLine("IEA*1*"//IEA01: number of functional groups +batchNum.ToString().PadLeft(9,'0')+"~");//IEA02: Interchange control number return strb.ToString(); /* return @" ISA*00* *00* *30*AA0989922 *30*330989922 *030519*1608*U*00401*000012145*1*T*:~ GS*HS*AA0989922*330989922*20030519*1608*12145*X*004010X092~ ST*270*0001~ BHT*0022*13*ASX012145WEB*20030519*1608~ HL*1**20*1~ NM1*PR*2*Metlife*****PI*65978~ HL*2*1*21*1~ NM1*1P*1*PROVLAST*PROVFIRST****XX*1234567893~ REF*TJ*200384584~ N3*JUNIT ROAD~ N4*CHICAGO*IL*60602~ PRV*PE*ZZ*1223G0001X~ HL*3*2*22*0~ TRN*1*12145*1AA0989922~ NM1*IL*1*SUBLASTNAME*SUBFIRSTNAME****MI*123456789~ DMG*D8*19750323~ DTP*307*D8*20030519~ EQ*30~ SE*17*0001~ GE*1*12145~ IEA*1*000012145~"; */ //return "ISA*00* *00* *30*AA0989922 *30*330989922 *030519*1608*U*00401*000012145*1*T*:~GS*HS*AA0989922*330989922*20030519*1608*12145*X*004010X092~ST*270*0001~BHT*0022*13*ASX012145WEB*20030519*1608~HL*1**20*1~NM1*PR*2*Metlife*****PI*65978~HL*2*1*21*1~NM1*1P*1*PROVLAST*PROVFIRST****XX*1234567893~REF*TJ*200384584~N3*JUNIT ROAD~N4*CHICAGO*IL*60602~PRV*PE*ZZ*1223G0001X~HL*3*2*22*0~TRN*1*12145*1AA0989922~NM1*IL*1*SUBLASTNAME*SUBFIRSTNAME****MI*123456789~DMG*D8*19750323~DTP*307*D8*20030519~EQ*30~SE*17*0001~GE*1*12145~IEA*1*000012145~"; }
///<summary>Checks dependencies first. Throws exception if can't delete.</summary> public static void Delete(Clinic clinic) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), clinic); return; } //Check FK dependencies. #region Patients string command = "SELECT LName,FName FROM patient WHERE ClinicNum =" + POut.Long(clinic.ClinicNum); DataTable table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; pats += table.Rows[i][0].ToString() + ", " + table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because it is in use by the following patients:") + pats); } #endregion #region Payments command = "SELECT patient.LName,patient.FName FROM patient,payment " + "WHERE payment.ClinicNum =" + POut.Long(clinic.ClinicNum) + " AND patient.PatNum=payment.PatNum"; table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; pats += table.Rows[i][0].ToString() + ", " + table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following patients have payments using it:") + pats); } #endregion #region ClaimPayments command = "SELECT patient.LName,patient.FName FROM patient,claimproc,claimpayment " + "WHERE claimpayment.ClinicNum =" + POut.Long(clinic.ClinicNum) + " AND patient.PatNum=claimproc.PatNum" + " AND claimproc.ClaimPaymentNum=claimpayment.ClaimPaymentNum " + "GROUP BY patient.LName,patient.FName,claimpayment.ClaimPaymentNum"; table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; pats += table.Rows[i][0].ToString() + ", " + table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following patients have claim payments using it:") + pats); } #endregion #region Appointments command = "SELECT patient.LName,patient.FName FROM patient,appointment " + "WHERE appointment.ClinicNum =" + POut.Long(clinic.ClinicNum) + " AND patient.PatNum=appointment.PatNum"; table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; pats += table.Rows[i][0].ToString() + ", " + table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following patients have appointments using it:") + pats); } #endregion #region Procedures //reassign procedure.ClinicNum=0 if the procs are status D. command = "UPDATE procedurelog SET ClinicNum=0 WHERE ProcStatus=" + POut.Int((int)ProcStat.D); Db.NonQ(command); command = "SELECT patient.LName,patient.FName FROM patient,procedurelog " + "WHERE procedurelog.ClinicNum =" + POut.Long(clinic.ClinicNum) + " AND patient.PatNum=procedurelog.PatNum"; table = Db.GetTable(command); if (table.Rows.Count > 0) { string pats = ""; for (int i = 0; i < table.Rows.Count; i++) { pats += "\r"; pats += table.Rows[i][0].ToString() + ", " + table.Rows[i][1].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following patients have procedures using it:") + pats); } #endregion #region Operatories command = "SELECT OpName FROM operatory " + "WHERE ClinicNum =" + POut.Long(clinic.ClinicNum); table = Db.GetTable(command); if (table.Rows.Count > 0) { string ops = ""; for (int i = 0; i < table.Rows.Count; i++) { ops += "\r"; ops += table.Rows[i][0].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following operatories are using it:") + ops); } #endregion #region Userod command = "SELECT UserName FROM userod " + "WHERE ClinicNum =" + POut.Long(clinic.ClinicNum); table = Db.GetTable(command); if (table.Rows.Count > 0) { string userNames = ""; for (int i = 0; i < table.Rows.Count; i++) { userNames += "\r"; userNames += table.Rows[i][0].ToString(); } throw new Exception(Lans.g("Clinics", "Cannot delete clinic because the following Open Dental users are using it:") + userNames); } #endregion //End checking for dependencies. //Clinic is not being used, OK to delete. command = "DELETE FROM clinic" + " WHERE ClinicNum = " + POut.Long(clinic.ClinicNum); Db.NonQ(command); }
private void Init(){ InitializeComponent(); breakLinePen.Width=2; if(etrans.PatNum!=0) { //Some transactions are not patient specific. patient=Patients.GetPat(etrans.PatNum); patPlansForPat=PatPlans.Refresh(etrans.PatNum); claim=Claims.GetClaim(etrans.ClaimNum); primaryCarrier=Carriers.GetCarrier(etrans.CarrierNum); if(claim==null) {//for eligibility //Get primary info insSub=InsSubs.GetSub(etrans.InsSubNum,new List<InsSub>()); subscriber=Patients.GetPat(insSub.Subscriber); insplan=InsPlans.GetPlan(etrans.PlanNum,new List<InsPlan>()); patPlanPri=PatPlans.GetFromList(patPlansForPat,insSub.InsSubNum); } else { //Get primary info insSub=InsSubs.GetSub(claim.InsSubNum,new List<InsSub>()); subscriber=Patients.GetPat(insSub.Subscriber); insplan=InsPlans.GetPlan(claim.PlanNum,new List<InsPlan>()); patPlanPri=PatPlans.GetFromList(patPlansForPat,insSub.InsSubNum); //Get secondary info if(claim.InsSubNum2!=0) { patPlanSec=PatPlans.GetFromList(patPlansForPat,claim.InsSubNum2); insSub2=InsSubs.GetSub(claim.InsSubNum2,new List<InsSub>()); subscriber2=Patients.GetPat(insSub2.Subscriber); insplan2=InsPlans.GetPlan(claim.PlanNum2,new List<InsPlan>()); secondaryCarrier=Carriers.GetCarrier(insplan2.CarrierNum); } //Provider info provTreat=Providers.GetProv(claim.ProvTreat); provBill=Providers.GetProv(claim.ProvBill); //Claim related info claimprocs=ClaimProcs.RefreshForClaim(claim.ClaimNum); long clinicNum=0; for(int i=0;i<claimprocs.Count;i++) { if(claimprocs[i].ClinicNum!=0) { clinicNum=claimprocs[i].ClinicNum; break; } } if(clinicNum!=0) { clinic=Clinics.GetClinic(clinicNum); } else if(!PrefC.GetBool(PrefName.EasyNoClinics) && Clinics.List.Length>0) { clinic=Clinics.List[0]; } } if(provTreat==null) { provTreat=Providers.GetProv(Patients.GetProvNum(patient)); } if(provBill==null) { provBill=Providers.GetProv(Patients.GetProvNum(patient)); } List<Procedure> procsAll=Procedures.Refresh(etrans.PatNum); extracted=Procedures.GetCanadianExtractedTeeth(procsAll); } if(MessageText==null || MessageText.Length<23) { throw new Exception("CCD message format too short: "+MessageText); } formData=new CCDFieldInputter(MessageText);//Input the fields of the given message. CCDField languageOfInsured=formData.GetFieldById("G27"); if(languageOfInsured!=null) { if(languageOfInsured.valuestr=="F") { isFrench=true; } } else if(subscriber!=null && subscriber.Language=="fr") { isFrench=true; } formatVersionNumber=formData.GetFieldById("A03").valuestr;//Must always exist so no error checking here. transactionCode=formData.GetFieldById("A04").valuestr;//Must always exist so no error checking here. if(formatVersionNumber=="04") {//FormId field does not exist in version 02 in any of the message texts. CCDField formIdField=formData.GetFieldById("G42");//Usually exists in version 04 response messages. //Only a few response transactions don't define field G42. So far, those are transactions 15 (Summary Reconciliation), 16 (Payment Reconciliation) and 24 (Email). //In these cases, we simply do not use the formId field later on in the display code. if(formIdField!=null) { formId=formIdField.valuestr; } } else {//Version 02 //Since there is no FormID field in version 02, we figure out what the formId should be based on the transaction type. if(transactionCode=="10") {//Eligibility Response. formId="08";//Eligibility Form } else if(transactionCode=="11") {//Claim Response. formId="03";//Claim Acknowledgement Form } else if(transactionCode=="21") {//EOB formId="01";//EOB Form CCDField g02=formData.GetFieldById("G02"); if(g02!=null && g02.valuestr=="Y") { formId="04";//Employer Certified. } } else if(transactionCode=="13") {//Response to Pre-Determination. formId="06";//Pre-Determination Acknowledgement Form } else if(transactionCode=="12") { //Reversal response //There is no standard form for a reversal response, but we print the reversal response later on based on the transactioncode so we don't need to do anything here. } else { throw new Exception("Unhandled transactionCode '"+transactionCode+"' for version 02 message."); } } CCDField status=formData.GetFieldById("G05"); if(status!=null && status.valuestr!=null) { responseStatus=status.valuestr.ToUpper(); } transactionCode=formData.GetFieldById("A04").valuestr; predetermination=(transactionCode=="23"||transactionCode=="13");//Be sure to list all predetermination response types here! if(copiesToPrint<=0) { //Show the form on screen if there are no copies to print. ShowDisplayMessages(); CCDField fieldPayTo=formData.GetFieldById("F01"); if(fieldPayTo!=null) { bool paySubscriber=(fieldPayTo.valuestr=="1");//same for version 02 and version 04 //Typically, insurance companies in Canada prefer to pay the subscriber instead of the dentist. if(AssignmentOfBenefits()) {//The insurance plan is set to pay the dentist if(paySubscriber) {//The carrier has decided to pay the subscriber. MsgBox.Show("Canadian","INFORMATION: The carrier changed the payee from the dentist to the subscriber.");//This check was required for certification. } } else {//The insurance plan is set to pay the subscriber if(!paySubscriber) {//The carrier has decided to pay the dentist. MsgBox.Show("Canadian","INFORMATION: The carrier changed the payee from the subscriber to the dentist.");//This check was required for certification. } } } CCDField paymentAdjustmentAmount=formData.GetFieldById("G33"); if(paymentAdjustmentAmount!=null) { if(paymentAdjustmentAmount.valuestr.Substring(1)!="000000") { MessageBox.Show(Lan.g(this,"Payment adjustment amount")+": "+RawMoneyStrToDisplayMoney(paymentAdjustmentAmount.valuestr)); } } if(autoPrint) { if(responseStatus!="R") { //We are not required to automatically print rejection notices. //Automatically print a patient copy only. We are never required to autoprint a dentist copy, but it can be done manually instead. new FormCCDPrint(etrans.Copy(),MessageText,1,false,true); } } if(formId=="05") { //Manual claim form Canadian.ShowManualClaimForm(claim); Close(); } else { pd=CreatePrintDocument(); printPreviewControl1.Document=pd;//Setting the document causes system to call pd_PrintPage, which will print the document in the preview window. ShowDialog(); } } else { pd=CreatePrintDocument(); if(formId=="05") { //Manual claim form #if DEBUG Canadian.ShowManualClaimForm(claim); #else Canadian.PrintManualClaimForm(claim);//Send the print job to the physical printer. #endif } else { #if DEBUG new FormCCDPrint(etrans.Copy(),MessageText,0,false,patientCopy);//Show the form on the screen. #else pd.Print();//Send the print job to the physical printer. #endif } //Print the remaining copies recursively. if(copiesToPrint>=2) { new FormCCDPrint(etrans.Copy(),MessageText,copiesToPrint-1,false,patientCopy); } } CCDField embeddedTransaction=formData.GetFieldById("G40"); if(embeddedTransaction!=null) { new FormCCDPrint(etrans.Copy(),embeddedTransaction.valuestr,copiesToPrint,autoPrint,patientCopy); } }
///<summary>Called by local practice db to query HQ for EService setup info. Must remain very lite and versionless. Will be used by signup portal. ///If HasClinics==true then any SignupOut.EServices entries where ClinicNum==0 are invalid and should be ignored. ///If HasClinics==false then SignupOut.EServices should only pay attention items where ClinicNum==0. ///This list is kept completely unfiltered by ClinicNum for forward compatibility reasons. ///The ClinicNum 0 items are always used by the Signup portal to determine default signup preferences. ///However, these items are only used for validation and billing in the case where HasClinics==true.</summary> public static EServiceSetup.SignupOut GetEServiceSetupFull(SignupPortalPermission permission, bool isSwitchClinicPref = false) { //Clinics will be stored in this order at HQ to allow signup portal to display them in proper order. List <Clinic> clinics = Clinics.GetDeepCopy().OrderBy(x => x.ItemOrder).ToList(); if (PrefC.GetBool(PrefName.ClinicListIsAlphabetical)) { clinics = clinics.OrderBy(x => x.Abbr).ToList(); } #if DEBUG bool isMockChanged = false; if (WebServiceMainHQProxy.MockWebServiceMainHQ == null) { WebServiceMainHQProxy.MockWebServiceMainHQ = new WebServiceMainHQMockDemo(); isMockChanged = true; } #endif EServiceSetup.SignupOut signupOut = ReadXml <EServiceSetup.SignupOut> ( WebSerializer.DeserializePrimitiveOrThrow <string> ( GetWebServiceMainHQInstance().EServiceSetup ( CreateWebServiceHQPayload ( WriteXml(new EServiceSetup.SignupIn() { MethodNameInt = (int)EServiceSetup.SetupMethod.GetSignupOutFull, HasClinics = PrefC.HasClinicsEnabled, //ClinicNum is not currently used as input. ClinicNum = 0, ProgramVersionStr = PrefC.GetString(PrefName.ProgramVersion), SignupPortalPermissionInt = (int)permission, Clinics = clinics .Select(x => new EServiceSetup.SignupIn.ClinicLiteIn() { ClinicNum = x.ClinicNum, ClinicTitle = x.Abbr, IsHidden = x.IsHidden, }).ToList(), IsSwitchClinicPref = isSwitchClinicPref, }), eServiceCode.Undefined ) ) ) ); #if DEBUG if (isMockChanged) { WebServiceMainHQProxy.MockWebServiceMainHQ = null; } #endif //We just got the latest sync info from HQ so update the local db to reflect what HQ says is true. #region Reconcile Phones List <SmsPhone> listPhonesHQ = signupOut.Phones.Select(x => new SmsPhone() { ClinicNum = x.ClinicNum, CountryCode = x.CountryCode, DateTimeActive = x.DateTimeActive, DateTimeInactive = x.DateTimeInactive, InactiveCode = x.InactiveCode, PhoneNumber = x.PhoneNumber, }).ToList(); SmsPhones.UpdateOrInsertFromList(listPhonesHQ); #endregion #region Reconcile practice and clinics List <EServiceSetup.SignupOut.SignupOutSms> smsSignups = GetSignups <EServiceSetup.SignupOut.SignupOutSms>(signupOut, eServiceCode.IntegratedTexting); bool isCacheInvalid = false; bool isSmsEnabled = false; if (PrefC.HasClinicsEnabled) //Clinics are ON so loop through all clinics and reconcile with HQ. { List <Clinic> listClinicsAll = Clinics.GetDeepCopy(); foreach (Clinic clinicDb in listClinicsAll) { WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms clinicSignup = smsSignups.FirstOrDefault(x => x.ClinicNum == clinicDb.ClinicNum) ?? new WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms() { //Not found so turn it off. SmsContractDate = DateTime.MinValue, MonthlySmsLimit = 0, IsEnabled = false, }; Clinic clinicNew = clinicDb.Copy(); clinicNew.SmsContractDate = clinicSignup.SmsContractDate; clinicNew.SmsMonthlyLimit = clinicSignup.MonthlySmsLimit; isCacheInvalid |= Clinics.Update(clinicNew, clinicDb); isSmsEnabled |= clinicSignup.IsEnabled; } } else //Clinics are off so ClinicNum 0 is the practice clinic. { WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms practiceSignup = smsSignups.FirstOrDefault(x => x.ClinicNum == 0) ?? new WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms() { //Not found so turn it off. SmsContractDate = DateTime.MinValue, MonthlySmsLimit = 0, IsEnabled = false, }; isCacheInvalid |= Prefs.UpdateDateT(PrefName.SmsContractDate, practiceSignup.SmsContractDate) | Prefs.UpdateLong(PrefName.TextingDefaultClinicNum, 0) | Prefs.UpdateDouble(PrefName.SmsMonthlyLimit, practiceSignup.MonthlySmsLimit); isSmsEnabled |= practiceSignup.IsEnabled; } #endregion #region Reconcile CallFire //Turn off CallFire if SMS has been activated. //This only happens the first time SMS is turned on and CallFire is still activated. if (isSmsEnabled && Programs.IsEnabled(ProgramName.CallFire)) { Program callfire = Programs.GetCur(ProgramName.CallFire); if (callfire != null) { callfire.Enabled = false; Programs.Update(callfire); Signalods.Insert(new Signalod() { IType = InvalidType.Providers }); signupOut.Prompts.Add("Call Fire has been disabled. Cancel Integrated Texting and access program properties to retain Call Fire."); } } #endregion #region eConfirmations if (Prefs.UpdateBool(PrefName.ApptConfirmAutoSignedUp, IsEServiceActive(signupOut, eServiceCode.ConfirmationRequest))) { //HQ does not match the local pref. Make it match with HQ. isCacheInvalid = true; SecurityLogs.MakeLogEntry(Permissions.Setup, 0, "Automated appointment eConfirmations automatically changed by HQ. Local pref set to " + IsEServiceActive(signupOut, eServiceCode.ConfirmationRequest).ToString() + "."); } #endregion if (isCacheInvalid) //Something changed in the db. Alert other workstations and change this workstation immediately. { Signalods.Insert(new Signalod() { IType = InvalidType.Prefs }); Prefs.RefreshCache(); Signalods.Insert(new Signalod() { IType = InvalidType.Providers }); Providers.RefreshCache(); Clinics.RefreshCache(); } return(signupOut); }