예제 #1
0
		///<summary></summary>
		public FormEtrans835ClaimPay(Hx835_Claim claimPaid,Claim claim,Patient patCur,Family famCur,List<InsPlan> planList,List<PatPlan> patPlanList,List<InsSub> subList) {
			InitializeComponent();
			_claimPaid=claimPaid;
			_claim=claim;
			_famCur=famCur;
			_patCur=patCur;
			_listPlans=planList;
			_listInsSubs=subList;
			_listPatPlans=patPlanList;
			Lan.F(this);
		}
예제 #2
0
		public FormEtrans835ClaimEdit(Hx835_Claim claimPaid) {
			InitializeComponent();
			Lan.F(this);
			_claimPaid=claimPaid;
		}
예제 #3
0
파일: X835.cs 프로젝트: mnisl/OD
		///<summary>2100 CLP: Claim Payment Information.  Required.  Repeat 1.  Guide page 123.</summary>
		private Hx835_Claim ProcessCLP(int segNum,string npi) {
			int segNumCLP=segNum;
			Hx835_Claim retVal=new Hx835_Claim();
			X12Segment segCLP=_listSegments[segNum];
			retVal.Npi=npi;
			retVal.ClaimTrackingNumber=segCLP.Get(1);//CLP01
			retVal.PayerControlNumber=segCLP.Get(7);//CLP07 Payer Claim Control Number
			retVal.StatusCodeDescript=GetDescriptForClaimStatusCode(segCLP.Get(2));//CLP02 Claim Status Code Description
			retVal.ClaimFee=PIn.Decimal(segCLP.Get(3));//CLP03 Total Claim Charge Amount
			retVal.InsPaid=PIn.Decimal(segCLP.Get(4));//CLP04 Claim Payment Amount
			retVal.PatientPortion=PIn.Decimal(segCLP.Get(5));//CLP05 Patient Portion Amount
			retVal.DateReceived=DateReceived;
			segNum++;
			retVal.ListClaimAdjustments=new List<Hx835_Adj>();
			//2100 CAS: Claim Adjustment.  Situational.  Repeat 99.  Guide page 129.
			while(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="CAS") {
				retVal.ListClaimAdjustments.AddRange(ProcessCAS(segNum));
				segNum++;
			}
			retVal.ClaimAdjustmentTotal=0;
			//2100 NM1: Patient Name.  Required.  Repeat 1.  Guide page 137.
			if(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="NM1" && _listSegments[segNum].Get(1)=="QC") {
				retVal.PatientName=ProcessNM1_Person(segNum);
				segNum++;
			}
			//2100 NM1: Insured Name.  Situational.  Required when different from the patient.  Repeat 1.  Guide page 140.
			retVal.SubscriberName=retVal.PatientName;
			if(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="NM1" && _listSegments[segNum].Get(1)=="IL") {
				retVal.SubscriberName=ProcessNM1_Person(segNum);
				segNum++;
			}
			//2100 NM1: Corrected Patient/Insured Name.  Situational.  Repeat 1.  Guide page 143.  We do not use.
			if(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="NM1" && _listSegments[segNum].Get(1)=="74") {
				segNum++;
			}
			//2100 NM1: Service Provider Name.  Situational.  Repeat 1.  Guide page 146.  We do not use.
			if(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="NM1" && _listSegments[segNum].Get(1)=="82") {
				segNum++;
			}
			//2100 NM1: Crossover Carrier Name.  Situational.  Repeat 1.  Guide page 150.  We do not use.
			if(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="NM1" && _listSegments[segNum].Get(1)=="TT") {
				segNum++;
			}
			//2100 NM1: Corrected Priority Payer Name.  Situational.  Repeat 1.  Guide page 153.  We do not use.
			if(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="NM1" && _listSegments[segNum].Get(1)=="PR") {
				segNum++;
			}
			//2100 NM1: Other Subscriber Name.  Situational.  Repeat 1.  Guide page 156.  We do not use.
			if(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="NM1" && _listSegments[segNum].Get(1)=="GB") {
				segNum++;
			}
			//2100 MIA: Inpatient Adjudication Information.  Situational.  Repeat 1.  Guide page 159. 
			retVal.ListAdjudicationInfo=new List<Hx835_Info>();
			if(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="MIA") {
				retVal.ListAdjudicationInfo.AddRange(ProcessMIA(segNum));
				segNum++;
			}
			//2100 MOA: Outpatient Adjudication Information.  Situational.  Repeat 1.  Guide page 166.
			if(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="MOA") {
				retVal.ListAdjudicationInfo.AddRange(ProcessMOA(segNum));
				segNum++;
			}
			retVal.IsSplitClaim=false;
			for(int i=0;i<retVal.ListAdjudicationInfo.Count;i++) {
				Hx835_Info info=retVal.ListAdjudicationInfo[i];
				if(info.IsRemarkCode && info.FieldValueRaw=="MA15") {
					retVal.IsSplitClaim=true;
					break;
				}
			}
			//2100 REF: Other Claim Releated Identification.  Situational.  Repeat 5.  Guide page 169.  We do not use.
			//2100 REF: Rendering Provider Identification.  Situational.  Repeat 10.  Guide page 171.  We do not use.
			while(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="REF") {//We clump 2 segments into a single loop, because neither segment is used, and there are multiple REF01 choices for each.
				segNum++;
			}
			//2100 DTM: Statement From or To Date.  Situational.  Required if at least one service line is missing a service date.  Service line dates override this date.  Repeat 2.  Guide page 173.
			retVal.DateServiceStart=DateTime.MinValue;
			retVal.DateServiceEnd=DateTime.MinValue;
			while(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="DTM" && (_listSegments[segNum].Get(1)=="232" || _listSegments[segNum].Get(1)=="233")) {
				if(_listSegments[segNum].Get(1)=="232") {
					retVal.DateServiceStart=DtmToDateTime(_listSegments[segNum].Get(2));
				}
				else {//_listSegments[segNum].Get(1)=="233"
					retVal.DateServiceEnd=DtmToDateTime(_listSegments[segNum].Get(2));
				}
				segNum++;
			}
			if(retVal.DateServiceStart!=DateTime.MinValue && retVal.DateServiceEnd==DateTime.MinValue) {//Start date was provided, but end date was not.
				retVal.DateServiceEnd=retVal.DateServiceStart;//The end date is the same as the start date.
			}
			else if(retVal.DateServiceStart==DateTime.MinValue && retVal.DateServiceEnd!=DateTime.MinValue) {//Start date not provided, but end date was.  Should not happen.  Just in case.
				retVal.DateServiceStart=retVal.DateServiceEnd;
			}
			//2100 DTM: Coverage Expiration Date.  Situational.  Repeat 1.  Guide page 175.  We do not use.
			while(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="DTM" && _listSegments[segNum].Get(1)=="036") {
				segNum++;
			}
			//2100 DTM: Claim Received Date.  Situational.  Repeat 1.  Guide page 177.
			retVal.DatePayerReceived=DateTime.MinValue;
			while(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="DTM" && _listSegments[segNum].Get(1)=="050") {
				retVal.DatePayerReceived=DtmToDateTime(_listSegments[segNum].Get(2));
				segNum++;
			}
			//2100 PER: Claim Contact Information.  Situational.  Repeat 2.  Guide page 179.  We do not use.
			while(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="PER") {
				segNum++;
			}
			//2100 AMT: Claim Supplemental Information.  Situational.  Repeat 13.  Guide page 182.
			retVal.ListSupplementalInfo=new List<Hx835_Info>();
			while(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="AMT") {
				retVal.ListSupplementalInfo.Add(ProcessAMT(segNum));
				segNum++;
			}
			//2100 QTY: Claim Supplemental Information Quantity.  Situational.  Repeat 14.  Guide page 184.  We do not use.
			while(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="QTY") {
				segNum++;
			}
			//===============================  PROCEDURES  =============================
			//2110 SVC Service Payment Information.  Situational.  Repeat 999.  Guide page 186.
			retVal.ListProcs=new List<Hx835_Proc>();
			while(segNum<_listSegments.Count && _listSegments[segNum].SegmentID=="SVC") {
				Hx835_Proc proc=ProcessSVC(segNum,retVal.DateServiceStart,retVal.DateServiceEnd);
				retVal.ListProcs.Add(proc);
				segNum+=proc.SegmentCount;
			}
			//Now modify the claim dates to encompass the procedure dates.  This step causes procedure dates to bubble up to the claim level when only service line dates are provided.
			for(int i=0;i<retVal.ListProcs.Count;i++) {
				Hx835_Proc proc=retVal.ListProcs[i];
				if(retVal.DateServiceStart.Year<1880) {
					retVal.DateServiceStart=proc.DateServiceStart;
				}
				else if(proc.DateServiceStart.Year>1880 && proc.DateServiceStart<retVal.DateServiceStart) {
					retVal.DateServiceStart=proc.DateServiceStart;
				}
				if(retVal.DateServiceEnd.Year<1880) {
					retVal.DateServiceEnd=proc.DateServiceEnd;
				}
				else if(proc.DateServiceEnd.Year>1880 && proc.DateServiceEnd>retVal.DateServiceEnd) {
					retVal.DateServiceEnd=proc.DateServiceEnd;
				}
			}
			retVal.SegmentCount=segNum-segNumCLP;
			retVal.Writeoff=retVal.ClaimFee-retVal.InsPaid-retVal.PatientPortion;
			retVal.AllowedAmt=retVal.InsPaid+retVal.PatientPortion;
			return retVal;
		}
예제 #4
0
		///<summary>Enter either by total and/or by procedure, depending on whether or not procedure detail was provided in the 835 for this claim.
		///This function creates the payment claimprocs and displays the payment entry window.</summary>
		public static void EnterPayment(Hx835_Claim claimPaid,Claim claim,bool isAutomatic) {
			Patient pat=Patients.GetPat(claim.PatNum);
			Family fam=Patients.GetFamily(claim.PatNum);
			List<InsSub> listInsSubs=InsSubs.RefreshForFam(fam);
			List<InsPlan> listInsPlans=InsPlans.RefreshForSubList(listInsSubs);
			List<PatPlan> listPatPlans=PatPlans.Refresh(claim.PatNum);
			List<ClaimProc> listClaimProcsForClaim=ClaimProcs.RefreshForClaim(claim.ClaimNum);
			ClaimProc cpByTotal=new ClaimProc();
			cpByTotal.DedApplied=(double)claimPaid.PatientPortion;
			cpByTotal.AllowedOverride=(double)claimPaid.AllowedAmt;
			cpByTotal.InsPayAmt=(double)claimPaid.InsPaid;
			cpByTotal.WriteOff=(double)claimPaid.Writeoff;
			List<ClaimProc> listClaimProcsToEdit=new List<ClaimProc>();
			//Automatically set PayPlanNum if there is a payplan with matching PatNum, PlanNum, and InsSubNum that has not been paid in full.
			long insPayPlanNum=0;
			if(claim.ClaimType!="PreAuth" && claim.ClaimType!="Cap") {//By definition, capitation insurance pays in one lump-sum, not over an extended period of time.
				//By sending in ClaimNum, we ensure that we only get the payplan a claimproc from this claim was already attached to or payplans with no claimprocs attached.
				List<PayPlan> listPayPlans=PayPlans.GetValidInsPayPlans(claim.PatNum,claim.PlanNum,claim.InsSubNum,claim.ClaimNum);
				if(listPayPlans.Count==1) {
					insPayPlanNum=listPayPlans[0].PayPlanNum;
				}
				else if(listPayPlans.Count>1 && !isAutomatic) {
					//More than one valid PayPlan.  Cannot show this prompt when entering automatically, because it would disrupt workflow.
					List<PayPlanCharge> listPayPlanCharges=PayPlanCharges.Refresh(claim.PatNum);
					FormPayPlanSelect FormPPS=new FormPayPlanSelect(listPayPlans,listPayPlanCharges);
					FormPPS.ShowDialog();
					if(FormPPS.DialogResult==DialogResult.OK) {
						insPayPlanNum=listPayPlans[FormPPS.IndexSelected].PayPlanNum;
					}
				}
			}
			//Choose the claimprocs which are not received.
			for(int i=0;i<listClaimProcsForClaim.Count;i++) {
				if(listClaimProcsForClaim[i].ProcNum==0) {//Exclude any "by total" claimprocs.  Choose claimprocs for procedures only.
					continue;
				}
				if(listClaimProcsForClaim[i].Status!=ClaimProcStatus.NotReceived) {//Ignore procedures already received.
					continue;
				}
				listClaimProcsToEdit.Add(listClaimProcsForClaim[i]);//Procedures not yet received.
			}
			//If all claimprocs are received, then choose claimprocs if not paid on.
			if(listClaimProcsToEdit.Count==0) {
				for(int i=0;i<listClaimProcsForClaim.Count;i++) {
					if(listClaimProcsForClaim[i].ProcNum==0) {//Exclude any "by total" claimprocs.  Choose claimprocs for procedures only.
						continue;
					}
					if(listClaimProcsForClaim[i].ClaimPaymentNum!=0) {//Exclude claimprocs already paid.
						continue;
					}
					listClaimProcsToEdit.Add(listClaimProcsForClaim[i]);//Procedures not paid yet.
				}
			}
			//For each NotReceived/unpaid procedure on the claim where the procedure information can be successfully located on the EOB, enter the payment information.
			List <List <Hx835_Proc>> listProcsForClaimProcs=claimPaid.GetPaymentsForClaimProcs(listClaimProcsToEdit);
			for(int i=0;i<listClaimProcsToEdit.Count;i++) {
				ClaimProc claimProc=listClaimProcsToEdit[i];
				List<Hx835_Proc> listProcsForProcNum=listProcsForClaimProcs[i];
				//If listProcsForProcNum.Count==0, then procedure payment details were not not found for this one specific procedure.
				//This can happen with procedures from older 837s, when we did not send out the procedure identifiers, in which case ProcNum would be 0.
				//Since we cannot place detail on the service line, we will leave the amounts for the procedure on the total payment line.
				//If listProcsForPorcNum.Count==1, then we know that the procedure was adjudicated as is or it might have been bundled, but we treat both situations the same way.
				//The 835 is required to include one line for each bundled procedure, which gives is a direct manner in which to associate each line to its original procedure.
				//If listProcForProcNum.Count > 1, then the procedure was either split or unbundled when it was adjudicated by the payer.
				//We will not bother to modify the procedure codes on the claim, because the user can see how the procedure was split or unbunbled by viewing the 835 details.
				//Instead, we will simply add up all of the partial payment lines for the procedure, and report the full payment amount on the original procedure.
				claimProc.DedApplied=0;
				claimProc.AllowedOverride=0;
				claimProc.InsPayAmt=0;
				claimProc.WriteOff=0;
				StringBuilder sb=new StringBuilder();
				for(int j=0;j<listProcsForProcNum.Count;j++) {
					Hx835_Proc procPaidPartial=listProcsForProcNum[j];
					claimProc.DedApplied+=(double)procPaidPartial.PatientPortion;
					claimProc.AllowedOverride+=(double)procPaidPartial.AllowedAmt;
					claimProc.InsPayAmt+=(double)procPaidPartial.InsPaid;
					claimProc.WriteOff+=(double)procPaidPartial.Writeoff;
					if(sb.Length>0) {
						sb.Append("\r\n");
					}
					sb.Append(procPaidPartial.GetRemarks());
				}
				claimProc.Remarks=sb.ToString();
				if(claim.ClaimType=="PreAuth") {
					claimProc.Status=ClaimProcStatus.Preauth;
				}
				else if(claim.ClaimType=="Cap") {
					//Do nothing.  The claimprocstatus will remain Capitation.
				}
				else {
					claimProc.Status=ClaimProcStatus.Received;
					claimProc.DateEntry=DateTime.Now;//Date is was set rec'd
					claimProc.PayPlanNum=insPayPlanNum;//Payment plans do not exist for PreAuths or Capitation claims, by definition.
				}
				claimProc.DateCP=DateTimeOD.Today;
			}
			//Displace the procedure totals from the "by total" payment, since they have now been accounted for on the individual procedure lines.  Totals will not be affected if no procedure details could be located.
			//If a total payment was previously entered manually, this will subtract the existing total payment from the new total payment, causing the new total payment to be discarded below where zero amounts are checked.
			for(int i=0;i<listClaimProcsForClaim.Count;i++) {
				ClaimProc claimProc=listClaimProcsForClaim[i];
				cpByTotal.DedApplied-=claimProc.DedApplied;
				cpByTotal.AllowedOverride-=claimProc.AllowedOverride;
				cpByTotal.InsPayAmt-=claimProc.InsPayAmt;
				cpByTotal.WriteOff-=claimProc.WriteOff;
			}
			bool isByTotalIncluded=true;
			//Do not create a total payment if the payment contains all zero amounts, because it would not be useful.  Written to account for potential rounding errors in the amounts.
			if(Math.Round(cpByTotal.DedApplied,2,MidpointRounding.AwayFromZero)==0
				&& Math.Round(cpByTotal.AllowedOverride,2,MidpointRounding.AwayFromZero)==0
				&& Math.Round(cpByTotal.InsPayAmt,2,MidpointRounding.AwayFromZero)==0
				&& Math.Round(cpByTotal.WriteOff,2,MidpointRounding.AwayFromZero)==0)
			{
				isByTotalIncluded=false;
			}
			if(claim.ClaimType=="PreAuth") {
				//In the claim edit window we currently block users from entering PreAuth payments by total, presumably because total payments affect the patient balance.
				isByTotalIncluded=false;
			}
			else if(claim.ClaimType=="Cap") {
				//In the edit claim window, we currently warn and discourage users from entering Capitation payments by total, because total payments affect the patient balance.
				isByTotalIncluded=false;
			}
			if(isByTotalIncluded) {
				cpByTotal.Status=ClaimProcStatus.Received;
				cpByTotal.ClaimNum=claim.ClaimNum;
				cpByTotal.PatNum=claim.PatNum;
				cpByTotal.ProvNum=claim.ProvTreat;
				cpByTotal.PlanNum=claim.PlanNum;
				cpByTotal.InsSubNum=claim.InsSubNum;
				cpByTotal.DateCP=DateTimeOD.Today;
				cpByTotal.ProcDate=claim.DateService;
				cpByTotal.DateEntry=DateTime.Now;
				cpByTotal.ClinicNum=claim.ClinicNum;
				cpByTotal.Remarks=claimPaid.GetRemarks();
				cpByTotal.PayPlanNum=insPayPlanNum;
				//Add the total payment to the beginning of the list, so that the ins paid amount for the total payment will be highlighted when FormEtrans835ClaimPay loads.
				listClaimProcsForClaim.Insert(0,cpByTotal);
			}
			FormEtrans835ClaimPay FormP=new FormEtrans835ClaimPay(claimPaid,claim,pat,fam,listInsPlans,listPatPlans,listInsSubs);
			FormP.ListClaimProcsForClaim=listClaimProcsForClaim;
			if(isAutomatic) {
				FormP.ReceivePayment();
			}
			else if(FormP.ShowDialog()!=DialogResult.OK) {
				if(cpByTotal.ClaimProcNum!=0) {
					ClaimProcs.Delete(cpByTotal);
				}
			}
		}