protected static void FeeTestSetup() { //Some unit tests cannot handle duplicate procedure codes being present within the database. //This is acceptable because that scenario should be impossible (we block the user via the UI layer). //Delete all duplicate procedure codes. Dictionary <string, ProcedureCode> dictProcCodes = ProcedureCodes.GetAllCodes().GroupBy(x => x.ProcCode).ToDictionary(x => x.Key, x => x.First()); ProcedureCodeT.ClearProcedureCodeTable(); foreach (ProcedureCode procedureCode in dictProcCodes.Values) { ProcedureCodes.Insert(procedureCode); } ProcedureCodes.RefreshCache(); _listProcCodes = ProcedureCodes.GetAllCodes(); //Just in case the PKs matter to some tests. _listProcCodesOld = _listProcCodes.Select(x => x.Copy()).ToList(); if (Fees.GetCountByFeeSchedNum(_standardFeeSchedNum) <= 0) { List <Fee> listFees = new List <Fee>(); foreach (ProcedureCode procCode in _listProcCodes) { listFees.Add(new Fee() { FeeSched = _standardFeeSchedNum, CodeNum = procCode.CodeNum, Amount = _defaultFeeAmt * _rand.NextDouble(), ClinicNum = 0, ProvNum = 0 }); //create the default fee schedule fee } Fees.InsertMany(listFees); } }
public static void SetUp(TestContext context) { _listProcCodes = ProcedureCodes.GetAllCodes(); List <Fee> listFees = new List <Fee>(); foreach (ProcedureCode procCode in _listProcCodes) { listFees.Add(new Fee() { FeeSched = _standardFeeSchedNum, CodeNum = procCode.CodeNum, Amount = _defaultFeeAmt * _rand.NextDouble(), ClinicNum = 0, ProvNum = 0 }); //create the default fee schedule fee } Fees.InsertMany(listFees); }
///<summary>Sets the MissingData and Warnings fields on the queueItem as appropriate.</summary> public static void GetMissingData(Clearinghouse clearinghouseClin, ClaimSendQueueItem queueItem) { StringBuilder sbErrors = new StringBuilder(); StringBuilder sbWarnings = new StringBuilder(); Claim claim = Claims.GetClaim(queueItem.ClaimNum); Provider provClaimTreat = Providers.GetProv(claim.ProvTreat); InsSub insSub = InsSubs.GetOne(claim.InsSubNum); #region Header //TRNSM if (!Regex.IsMatch(clearinghouseClin.SenderTIN, @"^[0-9]+$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Tax ID Number (RAMQ TRNSM) is invalid"); } else { int trnsm = PIn.Int(clearinghouseClin.SenderTIN); if (clearinghouseClin.ISA15 != "T" && trnsm >= 18000 && trnsm <= 18999) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Tax ID Number (RAMQ TRNSM) is a test value on this production claim"); } else if (clearinghouseClin.ISA15 == "T" && (trnsm < 18000 || trnsm > 18999)) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Tax ID Number (RAMQ TRNSM) must be between 18000 and 18999 for this test claim"); } } //DISP if (!Regex.IsMatch(provClaimTreat.NationalProvID, @"^[27][0-9]{5}$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Claim treating provider CDA Number for RAMQ is invalid"); } //DISP_REFNT if (claim.CanadianReferralProviderNum.Trim().Length > 0 && !Regex.IsMatch(claim.CanadianReferralProviderNum.Trim(), @"^[0-9]{6}$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Referral provider CDA Number for RAMQ is invalid"); } //ETAB if (!Regex.IsMatch(provClaimTreat.CanadianOfficeNum, @"^[0-9]{5}$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Claim treating provider Office Number for RAMQ is invalid"); } //SERV if (claim.DateService.Year < 1880) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Claim date of service is invalid or missing"); } #endregion Header #region Insurance //Most fields in the insuranace section are optional and thus do not require validation. //NAM if (!Regex.IsMatch(insSub.SubscriberID, @"^[a-zA-Z]{4}[0-9]{6}[a-zA-Z0-9][0-9]$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Subscriber ID for RAMQ is invalid"); } #endregion Insurance #region Procedures List <ProcedureCode> listProcCodes = ProcedureCodes.GetAllCodes(); List <ClaimProc> listClaimProcsForPat = ClaimProcs.Refresh(claim.PatNum); List <ClaimProc> listClaimProcsForClaim = ClaimProcs.GetForSendClaim(listClaimProcsForPat, claim.ClaimNum); //Excludes labs. List <Procedure> listProcsForPat = Procedures.Refresh(claim.PatNum); foreach (ClaimProc claimProc in listClaimProcsForClaim) { Procedure proc = Procedures.GetProcFromList(listProcsForPat, claimProc.ProcNum); if (proc.ProcFee == 0) { continue; } ProcedureCode procCode = ProcedureCodes.GetProcCode(proc.CodeNum, listProcCodes); if (procCode.NoBillIns) { continue; } //ACTE if (procCode.ProcCode.Length < 5 || !Regex.IsMatch(procCode.ProcCode.Substring(0, 5), @"^[0-9]{5}$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Procedure code invalid '" + procCode.ProcCode + "'"); } List <Procedure> listLabProcs = Procedures.GetCanadianLabFees(proc.ProcNum, listProcsForPat); foreach (Procedure labProc in listLabProcs) { if (labProc.ProcFee == 0) { continue; } ProcedureCode labProcCode = ProcedureCodes.GetProcCode(labProc.CodeNum, listProcCodes); if (labProcCode.ProcCode.Length < 5 || !Regex.IsMatch(labProcCode.ProcCode.Substring(0, 5), @"^[0-9]{5}$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Lab code invalid '" + labProcCode.ProcCode + "'"); } } } #endregion Procedures queueItem.MissingData = sbErrors.ToString(); queueItem.Warnings = sbWarnings.ToString(); }
///<summary>Called from Eclaims and includes multiple claims.</summary> public static string SendBatch(Clearinghouse clearinghouseClin, List <ClaimSendQueueItem> queueItems, int batchNum) { //STEP 1 - Build XML output. List <DP_RACINDP> listDps = new List <DP_RACINDP>(); List <ProcedureCode> listProcCodes = ProcedureCodes.GetAllCodes(); List <Etrans> listEtrans = new List <Etrans>(); foreach (ClaimSendQueueItem queueItem in queueItems) { Etrans etrans = Etranss.SetClaimSentOrPrinted(queueItem.ClaimNum, queueItem.PatNum, clearinghouseClin.HqClearinghouseNum, EtransType.Claim_Ramq, batchNum, Security.CurUser.UserNum); listEtrans.Add(etrans); //Now we need to update our cache of claims to reflect the change that took place in the database above in Etranss.SetClaimSentOrPrinted() queueItem.ClaimStatus = "S"; Claim claim = Claims.GetClaim(queueItem.ClaimNum); Provider provClaimTreat = Providers.GetProv(claim.ProvTreat); DP_RACINDP dp = new DP_RACINDP(); #region Header dp.CHN = DP_RACINDPCHN.Item06; dp.CHNSpecified = true; dp.ENRG = DP_RACINDPENRG.Item1; dp.ENRGSpecified = true; //We hijack the TaxID number for the TRNSM field. The TRNSM is a office identifying number. Test range for developers is 18000 to 18999. dp.TRNSM = clearinghouseClin.SenderTIN; dp.DISP = provClaimTreat.NationalProvID; //dp.CPTE_ADMN=;//Administrative account number. Not currently used. JulianCalendar calendar = new JulianCalendar(); dp.ATTES = (DateTime.Now.Year % 10).ToString() //One digit for year + calendar.GetDayOfYear(DateTime.Now).ToString().PadLeft(3, '0') //3 digits for Julian day of year. + (etrans.CarrierTransCounter % 1000).ToString().PadLeft(3, '0'); //3 digits for sequence number. dp.NCE = (etrans.CarrierTransCounter % 10000).ToString().PadLeft(4, '0'); dp.DISP_REFNT = claim.CanadianReferralProviderNum.Trim(); //dp.DIAGN=;//Diagnostic code. Not currently used. dp.ETAB = provClaimTreat.CanadianOfficeNum; //Usually empty. //dp.ADMIS=;//Date of patient admission. Not currently used. This would be the same as the date of service for dental claims anyway. //dp.SORTI=;//Date patient discharged. Not currently used. This would be the same as the date of service for dental claims anyway. dp.TOT_DEM = claim.ClaimFee.ToString().Replace(".", "").PadLeft(6, '0'); dp.COMPL = TidyStr(claim.ClaimNote, 200); //dp.CS=;//Not sure what this is. Not currently used. //dp.AUTOR=claim.PreAuthString;//Authorization number when invoicing acrylic prostheses. Required if DAT_AUTOR is present. Not currently used. //dp.DAT_AUTOR=claim.CanadianDateInitialLower;//Date of authorization when invoicing acrylic prostheses. Format YYMMDD. Not currently used. dp.SERV = claim.DateService.ToString("yyMMdd"); #endregion Header #region Insurance //Most fields in the insuranace section are optional. InsSub insSub = InsSubs.GetOne(claim.InsSubNum); dp.PERS_ASSU = new DP_RACINDPPERS_ASSU(); dp.PERS_ASSU.NAM = insSub.SubscriberID; Patient pat = Patients.GetPat(claim.PatNum); dp.PERS_ASSU.PRE = TidyStr(pat.FName, 20); dp.PERS_ASSU.NOM = TidyStr(pat.LName, 30); if (pat.Birthdate.Year > 1880) { dp.PERS_ASSU.NAISS = pat.Birthdate.ToString("yyyyMMdd"); } if (pat.Gender == PatientGender.Male) { dp.PERS_ASSU.SEXE = DP_RACINDPPERS_ASSUSEXE.M; } else if (pat.Gender == PatientGender.Female) { dp.PERS_ASSU.SEXE = DP_RACINDPPERS_ASSUSEXE.F; } else { //There is no value for UNKNOWN. This field is optional if the subscriber ID is present anyway. } List <PatPlan> listPatPlans = PatPlans.Refresh(claim.PatNum); PatPlan patPlan = PatPlans.GetByInsSubNum(listPatPlans, insSub.InsSubNum); dp.PERS_ASSU.CAM = patPlan.PatID; if (insSub.DateTerm.Year > 1880) { dp.PERS_ASSU.EXPIR_CAM = insSub.DateTerm.ToString("yyMM"); } InsPlan insPlan = InsPlans.RefreshOne(claim.PlanNum); InsPlan insPlan2 = InsPlans.RefreshOne(claim.PlanNum2); Carrier carrier = null; if (claim.ClaimType == "S") { carrier = Carriers.GetCarrier(insPlan2.CarrierNum); } else { carrier = Carriers.GetCarrier(insPlan.CarrierNum); } if (carrier.Address.Trim() != "") { dp.PERS_ASSU.ADR_1 = carrier.Address; dp.PERS_ASSU.ADR_2 = carrier.Address2; dp.PERS_ASSU.CP = carrier.Zip; } #endregion Insurance #region Procedures List <ClaimProc> listClaimProcsForPat = ClaimProcs.Refresh(claim.PatNum); List <ClaimProc> listClaimProcsForClaim = ClaimProcs.GetForSendClaim(listClaimProcsForPat, claim.ClaimNum); //Excludes labs. List <Procedure> listProcsForPat = Procedures.Refresh(claim.PatNum); List <DP_RACINDPACTE> listProcs = new List <DP_RACINDPACTE>(); foreach (ClaimProc claimProc in listClaimProcsForClaim) { Procedure proc = Procedures.GetProcFromList(listProcsForPat, claimProc.ProcNum); if (proc.ProcFee == 0) { continue; } ProcedureCode procCode = ProcedureCodes.GetProcCode(proc.CodeNum, listProcCodes); if (procCode.NoBillIns) { continue; } DP_RACINDPACTE acteProc = new DP_RACINDPACTE(); acteProc.ACTE = procCode.ProcCode; if (procCode.ProcCode.Length > 5) { acteProc.ACTE = procCode.ProcCode.Substring(0, 5); } acteProc.ROLE = "1"; //1 for principal role and 2 for assistant role. //acte.MODIF=;//Optional. Not sure what to put here, so leaving blank for now. acteProc.UNIT = proc.UnitQty.ToString().PadLeft(3, '0'); acteProc.MNT = proc.ProcFee.ToString("F").Replace(".", "").PadLeft(6, '0'); acteProc.DENT = proc.ToothNum.ToString().PadLeft(2, '0'); acteProc.SURF = proc.Surf.ToString().PadLeft(2, '0'); listProcs.Add(acteProc); List <Procedure> listLabProcs = Procedures.GetCanadianLabFees(proc.ProcNum, listProcsForPat); foreach (Procedure labProc in listLabProcs) { if (labProc.ProcFee == 0) { continue; } ProcedureCode labProcCode = ProcedureCodes.GetProcCode(labProc.CodeNum, listProcCodes); DP_RACINDPACTE acteLab = new DP_RACINDPACTE(); acteLab.ACTE = labProcCode.ProcCode; if (labProcCode.ProcCode.Length > 5) { acteLab.ACTE = labProcCode.ProcCode.Substring(0, 5); } acteLab.ROLE = "1"; //1 for principal role and 2 for assistant role. acteLab.MNT = labProc.ProcFee.ToString("F").Replace(".", "").PadLeft(6, '0'); listProcs.Add(acteLab); } } dp.ACTE = listProcs.ToArray(); #endregion Procedures listDps.Add(dp); } DP_RACIN batch = new DP_RACIN(); batch.DP = listDps.ToArray(); StringWriter sw = new StringWriter(); XmlSerializer serializer = new XmlSerializer(typeof(DP_RACIN)); serializer.Serialize(sw, batch); string xml = sw.ToString(); //Save a copy of the batch xml to each etrans entry (one per claim). EtransMessageText etransMsgText = new EtransMessageText(); etransMsgText.MessageText = xml; EtransMessageTexts.Insert(etransMsgText); foreach (Etrans etrans in listEtrans) { etrans.EtransMessageTextNum = etransMsgText.EtransMessageTextNum; Etranss.Update(etrans); } //Step 2 - ZIP XML and save to report path. The zip file name and file name within the zip file do not matter. string zipFilePath = CodeBase.ODFileUtils.CreateRandomFile(clearinghouseClin.ExportPath, ".zip", "claims"); ZipFile zip = null; try { zip = new ZipFile(); zip.UseZip64WhenSaving = Zip64Option.Always; zip.AddEntry("claims" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xml", xml); zip.Save(zipFilePath); zip.Dispose(); } catch (Exception ex) { ex.ToString(); if (zip != null) { zip.Dispose(); } if (File.Exists(zipFilePath)) { try { File.Delete(zipFilePath); } catch (Exception ex2) { ex2.ToString(); } } } return(xml); }
public static void SetUp(TestContext context) { _listProcCodes = ProcedureCodes.GetAllCodes(); _listProcCodesOrig = _listProcCodes.Select(x => x.Copy()).ToList(); }
public void Procedures_GlobalUpdateFees() { string name = MethodBase.GetCurrentMethod().Name; Random rand = new Random(); //set up fees List <Clinic> listClinics = new List <Clinic>(); for (int i = 0; i < 3; i++) { listClinics.Add(ClinicT.CreateClinic(name + "_" + i)); } List <long> listFeeSchedNums = new List <long>(); for (int i = 0; i < 2; i++) { listFeeSchedNums.Add(FeeSchedT.CreateFeeSched(FeeScheduleType.Normal, name + "_" + i, false)); } List <long> listProvNums = new List <long>(); for (int i = 0; i < 2; i++) { long feeSched = listFeeSchedNums[rand.Next(listFeeSchedNums.Count - 1)]; listProvNums.Add(ProviderT.CreateProvider(name + "_" + i, feeSchedNum: feeSched)); } List <ProcedureCode> listProcCodes = ProcedureCodes.GetAllCodes(); List <Fee> listFees = new List <Fee>(); foreach (ProcedureCode procCode in listProcCodes) { foreach (long feeSched in listFeeSchedNums) { foreach (Clinic clinic in listClinics) { foreach (long provNum in listProvNums) { listFees.Add(FeeT.GetNewFee(feeSched, procCode.CodeNum, 50 * rand.NextDouble(), clinic.ClinicNum, provNum)); } } } } //set up patients List <Patient> listPatients = new List <Patient>(); for (int i = 0; i < 3; i++) { listPatients.Add(PatientT.CreatePatient(name + "_" + i, listProvNums[rand.Next(listProvNums.Count - 1)], listClinics[rand.Next(listClinics.Count - 1)].ClinicNum)); } //TP some procedures List <Fee> listTPFees = new List <Fee>(); for (int i = 0; i < 100; i++) { ProcedureCode procCode = listProcCodes[rand.Next(listProcCodes.Count - 1)]; Patient patient = listPatients[rand.Next(listPatients.Count - 1)]; Fee fee = Fees.GetFee(procCode.CodeNum, Providers.GetProv(patient.PriProv).FeeSched, patient.ClinicNum, patient.PriProv); Procedure proc = ProcedureT.CreateProcedure(patient, procCode.ProcCode, ProcStat.TP, "", fee.Amount); listTPFees.Add(fee); } //change some of the fees List <Fee> listTPFeesChanged = listTPFees.OrderBy(x => rand.Next()).Take(50).ToList(); List <Fee> listNonTPFeesChanged = (listFees.Except(listTPFees)).OrderBy(x => rand.Next()).Take(50).ToList(); FeeCache cache = new FeeCache(listTPFeesChanged.Union(listNonTPFeesChanged).ToList()); cache.BeginTransaction(); foreach (Fee fee in listTPFeesChanged) { fee.Amount = 50 * rand.NextDouble(); cache.Update(fee); } foreach (Fee fee in listNonTPFeesChanged) { fee.Amount = 50 * rand.NextDouble(); cache.Update(fee); } cache.SaveToDb(); //Run the global update long updatedCount = 0; cache = new FeeCache(); for (int i = 0; i < listClinics.Count; i++) { updatedCount += Procedures.GlobalUpdateFees(cache.GetFeesForClinics(listClinics.Select(x => x.ClinicNum)), listClinics[i].ClinicNum, listClinics[i].Abbr); } //check the counts are the same List <Fee> listToCount = listTPFees.Where(x => listTPFeesChanged.Select(y => y.FeeNum).Contains(x.FeeNum)).ToList(); Assert.AreEqual(listToCount.Count, updatedCount); }
public static void SetUp(TestContext context) { _listProcCodes = ProcedureCodes.GetAllCodes(); }
///<summary>Sets the MissingData and Warnings fields on the queueItem as appropriate.</summary> public static void GetMissingData(ClaimSendQueueItem queueItem) { StringBuilder sbErrors = new StringBuilder(); StringBuilder sbWarnings = new StringBuilder(); Claim claim = Claims.GetClaim(queueItem.ClaimNum); Provider provClaimTreat = Providers.GetProv(claim.ProvTreat); InsSub insSub = InsSubs.GetOne(claim.InsSubNum); Patient pat = Patients.GetPat(claim.PatNum); #region Header //DISP if (!Regex.IsMatch(provClaimTreat.NationalProvID, @"^[27][0-9]{5}$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Claim treating provider ID for RAMQ is invalid"); } //DISP_REFNT if (claim.CanadianReferralProviderNum.Trim().Length > 0 && !Regex.IsMatch(claim.CanadianReferralProviderNum.Trim(), @"^[0-9]{6}$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Referral provider ID for RAMQ is invalid"); } //ETAB if (!Regex.IsMatch(provClaimTreat.CanadianOfficeNum, @"^[0-9]{5}$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Claim treating provider office number is invalid"); } //SERV if (claim.DateService.Year < 1880) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Claim date of service is invalid or missing"); } #endregion Header #region Insurance //Most fields in the insuranace section are optional and thus do not require validation. //NAM if (!Regex.IsMatch(insSub.SubscriberID, @"^[a-zA-Z]{4}[0-9]{6}[a-zA-Z0-9][0-9]$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Subscriber ID invalid"); } #endregion Insurance #region Procedures List <ProcedureCode> listProcCodes = ProcedureCodes.GetAllCodes(); List <ClaimProc> listClaimProcsForPat = ClaimProcs.Refresh(claim.PatNum); List <ClaimProc> listClaimProcsForClaim = ClaimProcs.GetForSendClaim(listClaimProcsForPat, claim.ClaimNum); //Excludes labs. List <Procedure> listProcsForPat = Procedures.Refresh(claim.PatNum); foreach (ClaimProc claimProc in listClaimProcsForClaim) { Procedure proc = Procedures.GetProcFromList(listProcsForPat, claimProc.ProcNum); if (proc.ProcFee == 0) { continue; } ProcedureCode procCode = ProcedureCodes.GetProcCode(proc.CodeNum, listProcCodes); if (procCode.NoBillIns) { continue; } //ACTE if (procCode.ProcCode.Length < 5 || !Regex.IsMatch(procCode.ProcCode.Substring(0, 5), @"^[0-9]{5}$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Procedure code invalid '" + procCode.ProcCode + "'"); } List <Procedure> listLabProcs = Procedures.GetCanadianLabFees(proc.ProcNum, listProcsForPat); foreach (Procedure labProc in listLabProcs) { if (labProc.ProcFee == 0) { continue; } ProcedureCode labProcCode = ProcedureCodes.GetProcCode(labProc.CodeNum, listProcCodes); if (labProcCode.ProcCode.Length < 5 || !Regex.IsMatch(labProcCode.ProcCode.Substring(0, 5), @"^[0-9]{5}$")) { if (sbErrors.Length != 0) { sbErrors.Append(","); } sbErrors.Append("Lab code invalid '" + labProcCode.ProcCode + "'"); } } } #endregion Procedures queueItem.MissingData = sbErrors.ToString(); queueItem.Warnings = sbWarnings.ToString(); }