public IEnumerable <Model.InvoiceRecord> LoadInvoiceRecords(Model.OrderSection section, Model.ProphSubsection subsection) { string sql = SectionizeQuery(Queries.SELECT_INVOICE_PEOPLE, section, subsection); sql = RecoursizeQuery(sql); return(aInvoice.Load(connectionMain, LocalizeQuery(sql))); }
public IEnumerable <Model.Recourse> LoadRecourses(Model.InvoiceRecord irec, Model.OrderSection section, Model.ProphSubsection subsection) { // Query is cached if (section != lastRecoursesSection || lastRecourceSubsection != subsection) { selectRecourses = null; lastRecoursesSection = section; lastRecourceSubsection = subsection; } if (selectRecourses == null) { string sql = LocalizeQuery(Queries.SELECT_RECOURSES); sql = RecoursizeQuery(sql); selectRecourses = connectionAlt.CreateCommand(); selectRecourses.CommandText = SectionizeQuery(sql, section, subsection); AddStringParameters(selectRecourses, SELECT_RECOURSE_CASES_PARAMS); } string id = string.Format("{0,6}", irec.Person.Identity); selectRecourses.Parameters[0].Value = id; List <RecourseAux> rs = aRecourse.Load(selectRecourses).ToList(); foreach (RecourseAux ra in rs) { Model.Recourse rec = ra.ToRecourse(); invox.Dict.ResultOutcome.Instance.Repair(rec); rec.Events = LoadEvents(rec, ra, section); yield return(rec); } }
/// <summary> /// Подставить в запрос коды отделений в соответствие разделу приложения Д к приказу /// </summary> string SectionizeQuery(string sql, Model.OrderSection section, Model.ProphSubsection subsection) { switch (section) { case Model.OrderSection.D1: return(sql.Replace(APPENDIX_SECTION_MARKER, D1_SELECTION)); case Model.OrderSection.D2: return(sql.Replace(APPENDIX_SECTION_MARKER, D2_SELECTION)); case Model.OrderSection.D3: switch (subsection) { case Model.ProphSubsection.Stage1: return(sql.Replace(APPENDIX_SECTION_MARKER, D3_SELECTION_STAGE1)); case Model.ProphSubsection.Stage2: return(sql.Replace(APPENDIX_SECTION_MARKER, D3_SELECTION_STAGE2)); case Model.ProphSubsection.Prophylaxis: return(sql.Replace(APPENDIX_SECTION_MARKER, D3_SELECTION_PROF)); default: throw new NotImplementedException(); } case Model.OrderSection.D4: return(sql.Replace(APPENDIX_SECTION_MARKER, D4_SELECTION)); } return(sql); }
public decimal Total(Model.OrderSection section, Model.ProphSubsection subsection) { string sql = SectionizeQuery(Queries.SELECT_TOTAL, section, subsection); object result = ExecuteScalar(connectionMain, LocalizeQuery(sql)); return(result != null && result != DBNull.Value ? (decimal)result : 0); }
public IEnumerable <Model.Person> LoadPeople(Model.OrderSection section, Model.ProphSubsection subsection) { string sql = SectionizeQuery(Queries.SELECT_PEOPLE, section, subsection); sql = RecoursizeQuery(sql); return(aPerson.Load(connectionMain, LocalizeQuery(sql))); }
/// <summary> /// Создать событие и заполнить его доступными полями /// </summary> public Model.Event ToEvent(Model.Recourse rec, Model.OrderSection section) { Model.Event result = new Model.Event(); // result.Services; - Pool.LoadEvents result.Identity = ServiceId; result.Unit = Unit; if (rec.IsHospitalization) { result.BedProfile = BedProfile; result.Transfer = Model.Transfer.Independently; } else { result.Transfer = Model.Transfer.None; } result.Child = Child; result.Reason = AidConditions == "3" ? InternalReasonHelper.ToVisitAim(InternalReason) : string.Empty; #if FOMS result.LocalReason = InternalReason.ToFomsReason(soul); #endif result.CardNumber = CardNumber; //result.Transfer; - Pool.LoadEvents //result.DateFrom; - Pool.LoadEvents result.DateTill = Date; //result.BedDays; - Pool.LoadEvents //result.PrimaryDiagnosis; - Pool.LoadEvents result.MainDiagnosis = MainDiagnosis; //result.FirstIdentified; - Pool.LoadEvents //result.ConcurrentDiagnosis; - Pool.LoadEvents //result.ComplicationDiagnosis; - Pool.LoadEvents //result.DispensarySupervision; - Pool.LoadEvents //result.ConcurrentMesCode; - Pool.LoadEvents // Hack to avoid oncology treatment services in polyclinic //result.Rehabilitation = Rehabilitation || (section == Model.OrderSection.D4 && !rec.SuspectOncology); result.Rehabilitation = Rehabilitation && !rec.SuspectOncology; result.Quantity = Quantity; result.SpecialityCode = SpecialityCode; result.DoctorCode = DoctorCode; //result.Tariff; - Pool.LoadEvents //result.Total; - Pool.LoadEvents // TODO: RecourseAux - HiTech data //result.HiTechKind; //result.HiTechMethod; //result.HiTechCheckDate; //result.HiTechCheckNumber; //result.HiTechPlannedHospitalizationDate; return(result); }
public int GetInvoiceRecordsCount(Model.OrderSection section, Model.ProphSubsection subsection) { string sql = SectionizeQuery(Queries.SELECT_INVOICE_RECORDS_COUNT, section, subsection); sql = RecoursizeQuery(sql); object result = ExecuteScalar(connectionMain, LocalizeQuery(sql)); return(result != null && result != DBNull.Value ? (int)(decimal)result : 0); }
static bool Run(Data.IInvoice pool, Model.OrderSection section, ref int packet) { foreach (Model.ProphSubsection s in Model.ProphSubsectionHelper.GetSubsections(section, Options.Pediatric)) { Lib.InvoiceFilename files = Lib.InvoiceFilename.ToAssuranceFund( Options.LpuCode, Options.FomsCode, Options.Year, Options.Month, ++packet, section, s); Model.Invoice invoice = new Model.Invoice(files); if (!invoice.Export(pool, Options.OutputLocation, Options.LeaveFiles)) { Console.WriteLine("\r\nОшибка!\r\n"); return(false); } } return(true); }
/// <summary> /// Загрузить события для законченного случая /// </summary> /// <remarks> /// В настоящий момент одному законченному случаю соответствует одно события (т.к. нет /// внутрибольничных переводов). Здесь также загружаются услуги для события и обновляются /// поля законченного случая данными, которые удалось получить на этом этапе. /// </remarks> List <Model.Event> LoadEvents(Model.Recourse rec, RecourseAux ra, Model.OrderSection section) { // Extract single event from the RecourseAux: List <Model.Event> result = new List <Model.Event>(); Model.Event evt = ra.ToEvent(rec, section); result.Add(evt); // Load auxilliary service records and service models List <ServiceAux> ss = LoadServices(ra, evt).Distinct(new ServiceComparer()).OrderBy(s => s.Date).ToList(); if (ra.InternalReason == InternalReason.SurgeryDayHosp && ss.Count(s => s.ServiceCode == ra.ServiceCode) > 1) { // Fix for: // Два случая ЦАХ у одного пациента с одним и тем же диагнозом // будут выгружены как два случая, но в каждом ВСЕ услуги из обеих госпитализаций // Get main service ServiceAux sa = ss.FirstOrDefault(s => s.Date == ra.Date && s.ServiceCode == ra.ServiceCode); if (sa != null) { // Get hospitalization dates DateTime till = sa.Date; DateTime from = till.WorkingDaysBefore(sa.BedDays, true); // Select only services with relevant dates IEnumerable <ServiceAux> sas = ss.Where(s => s.Date <= till && s.Date >= from); ra.UpdateMedicalAid(rec, sas.Last()); evt.Services = sas.Select(s => s.ToService(ra)).ToList(); // ...supposedly at least one services is selected: the main one } else { ra.UpdateMedicalAid(rec, ss.Last()); evt.Services = ss.Select(s => s.ToService(ra)).ToList(); } } else { ra.UpdateMedicalAid(rec, ss.Last()); evt.Services = ss.Select(s => s.ToService(ra)).ToList(); } // 20190902 - Блядский вид медицинского вмешательства if (ra.InternalReason == InternalReason.SurgeryDayHosp) { Model.Service service = evt.Services.FirstOrDefault(s => s.ServiceCode / 100000 == 3); if (service != null) { string interventionKind = GetInterventionKind(service.ServiceCode); if (!string.IsNullOrEmpty(interventionKind)) { evt.Services.ForEach(s => s.InterventionKind = interventionKind); } } } // Код врача и специальности должны соответствовать закрывающей записи, // приводим в соответствие из ra (где было изменено в UpdateMedicalAid()) evt.SpecialityCode = ra.SpecialityCode; evt.DoctorCode = ra.DoctorCode; if (rec.IsHospitalization) { // Update profile-shifting transfer and total of the bed days ServiceAux serv = ss.Where(s => s.Transfer == Model.Transfer.Transferred).FirstOrDefault(); // Turn transfer to ProfileShift if there has been bed profile change: if (serv != null && ss.GroupBy(s => s.BedProfile).Count() > 1) { serv.Transfer = Model.Transfer.ProfileShift; } evt.BedDays = ss.Select(s => s.BedDays).Sum(); } // Event dates if (ra.InternalReason == InternalReason.Stage1 || ra.InternalReason == InternalReason.Prof) { evt.DateTill = evt.Services.Max(s => s.DateTill); // For DD1 - start of the recourse is an antropometry ServiceAux sa = ss.Where(s => s.IsAntropometry()).FirstOrDefault(); if (sa != null) { evt.DateFrom = sa.Date; } else { evt.DateFrom = ss.Min(s => s.Date); } #if FOMS1 } else if (ra.InternalReason == InternalReason.Prof) { // Work around error "Код способа оплаты не соответствует периоду лечения; // Цель обращения не соответствует способу оплаты медицинской помощи" // Prof events within a single day are discarded with this error evt.DateFrom = ra.Date.ShiftDays(-1); if (evt.DateFrom == ra.Date) { evt.DateTill = ra.Date.ShiftDays(1); Model.Service s = evt.Services.First(); if (s != null) { s.DateFrom = evt.DateTill; s.DateTill = evt.DateTill; } } else { evt.DateTill = ra.Date; } #endif } else { // For other cases service with minimal date (mayhap hospitalization - reason why not ss.Min()) // 2 этап - пустая выборка try { evt.DateFrom = evt.Services.Min(s => s.DateFrom); } catch (Exception e) { Logger.Log(e.Message + string.Format(" - повод {0}, услуга {1}, S.RECID {2}", ra.InternalReason, ra.ServiceCode, ra.ServiceId)); } evt.DateTill = evt.Services.Max(s => s.DateTill); } #if FOMS // Задолбал ФОМС с их дурацкими ошибками: дд раз в 2 года ставит "неправильные даты", если дата начала и окончания не совпадают // В подушевой услуге ставим даты начала и окончания как во всем закрытом случае // 20190417 Хрен там, теперь не только обрезанная ДД Model.Service ser = evt.Services.FirstOrDefault(s => s.ServiceCode / 10000 == 5); if (ser != null) { ser.DateFrom = evt.DateFrom; ser.DateTill = evt.DateTill; } #endif // May change evt and ra's MainDiagnosis: ra.FindConcurrentDiagnoses(evt, ss, section); // Service diagnosis as recorse's in case of diagnostics if (ra.InternalReason == InternalReason.Diagnostics) { evt.Services.ForEach(s => s.Diagnosis = ra.MainDiagnosis); } evt.ComplicationDiagnoses = ServiceAux.GetComplicationDiagnoses(ss); // Statistic code if (!string.IsNullOrEmpty(ra.MainDiagnosis) && ra.MainDiagnosis.First() != 'Z') { StatisticCode[] sc = ss .Select(s => s.StatisticCode) .Where(s => s > StatisticCode.None && s < StatisticCode.Dispensary) .ToArray(); if (sc != null && sc.Count() > 0) { evt.StatisticsCode = (((int)sc.Max()) - 1).ToString(); } else { evt.StatisticsCode = Dict.StatisticsCode.Instance.Get(ra.MainDiagnosis); } } // Профиль МП случая - по профилю закрывающей записи rec.Profile = ss.OrderBy(s => s.Date).Last().AidProfile; // Other Event fields which can be taken from the services evt.Tariff = evt.Services.Sum(s => s.Tariff); evt.Total = evt.Services.Sum(s => s.Total); evt.PrimaryDiagnosis = ss.Max(s => s.PrimaryDiagnosis); evt.FirstIdentified = ss.Any(s => s.FirstIdentified); if (ra.InternalReason == InternalReason.DispRegister) { evt.DispensarySupervision = ss.Max(s => s.DispensarySupervision); if (evt.DispensarySupervision == Model.DispensarySupervision.None) { evt.DispensarySupervision = Model.DispensarySupervision.Observed; } } else if (section == Model.OrderSection.D3) { // 20190430 - D3 section: disp supervision is explicit evt.DispensarySupervision = ss.Max(s => s.DispensarySupervision); // Диагнозы на R ФОМС считает подлежащими Д-учету if (evt.DispensarySupervision < Model.DispensarySupervision.Observed || evt.DispensarySupervision > Model.DispensarySupervision.NotSubject) { if ("ZY".Contains(evt.MainDiagnosis.First())) { evt.DispensarySupervision = Model.DispensarySupervision.NotSubject; } else { if (evt.FirstIdentified) { evt.DispensarySupervision = Model.DispensarySupervision.Taken; } else { evt.DispensarySupervision = Model.DispensarySupervision.Observed; } } } } evt.ConcurrentMesCode = ss.Max(s => s.ConcurrentMesCode); var d2 = ss.Where(s => s.Transfer != Model.Transfer.None); if (d2 != null && d2.Count() > 0) { evt.Transfer = d2.Min(s => s.Transfer); } // Other Recourse fields -"- rec.UnitShift = ss.Any(s => s.Transfer == Model.Transfer.ProfileShift); rec.BirthWeight = ss.Max(s => s.BirthWeight); rec.DateFrom = evt.DateFrom; rec.DateTill = evt.DateTill; rec.Total = evt.Total; rec.BedDays = evt.BedDays; if (RecourseAux.NeedsDirection(rec)) { // Extract directed-from in case when it is needed rec.DirectedFrom = ss.Max(s => s.DirectedFrom); if (string.IsNullOrEmpty(rec.DirectedFrom)) { // TODO: LPU code from local to federal rec.DirectedFrom = Options.LpuCode; } rec.DirectionDate = rec.DateFrom; } return(result); }
public static InvoiceFilename ToAssuranceCompany(string lpuCode, string assuranceCompanyCode, int year, int month, int packetNumber, Model.OrderSection orderSection, Model.ProphSubsection subSection) { StringBuilder sb = new StringBuilder(); // Source sb.Append('M'); sb.Append(lpuCode); // Destination sb.Append('S'); sb.Append(assuranceCompanyCode); sb.Append('_'); sb.Append(year % 100); sb.Append(month.ToString("D2")); sb.Append((packetNumber % 100).ToString("D2")); string bulk = sb.ToString(); string invoice = null; string persons = null; switch (orderSection) { case Model.OrderSection.D1: invoice = "H" + bulk; persons = "L" + bulk; break; case Model.OrderSection.D2: invoice = "T" + bulk; persons = "LT" + bulk; break; case Model.OrderSection.D3: bulk = Model.ProphSubsectionHelper.GetCode(subSection) + bulk; invoice = "D" + bulk; persons = "L" + bulk; break; case Model.OrderSection.D4: invoice = "C" + bulk; persons = "LC" + bulk; break; } return(new InvoiceFilename(persons, invoice) { clinicCode = lpuCode, smoCode = assuranceCompanyCode, section = orderSection, subsection = subSection, year = year, month = month, code = (year % 100) * 10000 + month * 100 + (packetNumber % 100) }); }
/// <summary> /// Загрузить сопутствующие заболевания для события /// </summary> /// <param name="evt">Событие, которому требуется установить сопутствующие заболевания</param> /// <param name="services">Услуги, оказанные в рамках события. Сопутствующие берутся из них</param> public void FindConcurrentDiagnoses(Model.Event evt, List <ServiceAux> services, Model.OrderSection section) { var d1 = services.Select(s => s.ConcurrentDiagnosis) .Where(d => !string.IsNullOrEmpty(d) && d != evt.MainDiagnosis) .Distinct(); if (d1.Count() > 0) { evt.ConcurrentDiagnoses = d1.ToList(); } else { evt.ConcurrentDiagnoses = null; } // Проверить соответствие диагноза цели обращения (только для разделов D1 и D4) if (section == Model.OrderSection.D1 || section == Model.OrderSection.D4) { DiagnosisKind kind = InternalReason.GetDiagnosisKind(); if (!kind.Matches(MainDiagnosis)) { // Если не соответствует // Переносим основное заболевание в сопутствующие if (evt.ConcurrentDiagnoses == null) { evt.ConcurrentDiagnoses = new List <string>(); } evt.ConcurrentDiagnoses.Add(MainDiagnosis); // Попытаться найти подходящий в услугах... d1 = services.Select(s => s.PrimaryDiagnosis).Where(d => kind.Matches(d)); if (d1.Count() > 0) { evt.MainDiagnosis = MainDiagnosis = d1.First(); } else { // ...либо поставить диагноз по умолчанию if (kind == DiagnosisKind.Treatment) { Lib.Logger.Log(string.Format("Не найден подходящий диагноз для случая лечебной цели: RECID {0} (диагноз {1})", evt.CardNumber, MainDiagnosis)); } evt.MainDiagnosis = MainDiagnosis = InternalReason.DefaultDiagnosis(); evt.Services.ForEach(s => s.Diagnosis = MainDiagnosis); } } } }