protected override async Task <Card> HandleCore(DisabilitySheetHookContext context) { if (_options.AvailableKindDisabilityCodes.Any( a => a.Equals(context.KindDisabilityCode, StringComparison.CurrentCultureIgnoreCase)) == false) { return(new Card("Правило для указанного вида нетрудоспособности не проверяеться", Indicator.Info, new Link(""))); } var isTuberculosisConditioninRequest = _options.TuberculosisMkbDiagnosis.Any(t => context.DiagnosisCode.ToLowerInvariant().StartsWith(t)); var requestingDays = (context.TreatmentEnd.Date - context.TreatmentStart.Date).Days + 1; var calculateDaysSql = "CASE WHEN start< (current_date - interval '1 year') THEN \"end\"::date-(current_date - interval '1 year')::date+1 ELSE \"end\"::date-start::date+1 END"; var sqlGetDays = $@"SELECT SUM(CASE WHEN LOWER(diagnosis_code) SIMILAR TO '({string.Join("|", _options.TuberculosisMkbDiagnosis)})%' THEN {(isTuberculosisConditioninRequest ? calculateDaysSql : 0.ToString())} ELSE {(isTuberculosisConditioninRequest == false ? calculateDaysSql : 0.ToString())} END) AS days FROM episodeofcare eoc INNER JOIN episodeofcare_condition ecc ON ecc.episodeofcare_id = eoc.id INNER JOIN condition ec ON ec.id = ecc.condition_id AND ec.status = 'Confirmed' INNER JOIN composition com ON com.episodeofcare_id = eoc.id and com.status != 'entered-in-error' " + "WHERE \"end\">(current_date - interval '1 year') and eoc.status!='cancelled' and com.subject_id = @PatientId and eoc.id!=@EpisodeOfCareId"; var queryParam = new { PatientId = context.FreedPersonId, context.EpisodeOfCareId, }; var query = ( await _unitOfWork.QueryAsync( (connection, transaction) => connection.QueryAsync <long?>(sqlGetDays, queryParam, transaction))).First(); var queryResult = query ?? 0; var usedDaysInLastYear = queryResult; var maximumYearDays = isTuberculosisConditioninRequest ? _options.MaximumTuberculosisDaysCount : _options.MaximumDaysCountWithoutTuberculosis; if (usedDaysInLastYear + requestingDays > maximumYearDays) { return(new Card("Превышение общего периода нетрудоспособности за последние 12 месяцев.", Indicator.HardStop, new Link(""))); } if (usedDaysInLastYear + requestingDays >= maximumYearDays - _options.DaysPriorToExcees) { return(new Card("Превышение общего периода нетрудоспособности за последние 12 месяцев.", Indicator.Warning, new Link(""))); } return(new Card("Правило пройдено успешно", Indicator.Success, new Link(""))); }
protected override async Task <Card> HandleCore(DisabilitySheetHookContext context) { var sql = @" SELECT eoc.start as beginDate, eoc.end as endDate FROM episodeofcare eoc JOIN composition c on c.episodeofcare_id = eoc.id where c.status != 'entered-in-error' and eoc.status!='cancelled' and eoc.patient_id = @PatientId and (eoc.id!=@EpisodeOfCareId or @EpisodeOfCareId is null); "; //temporary data var hardStopQueryParameters = new { context.PatientId, context.EpisodeOfCareId }; var hardStopRange = new DateRange() { BeginDate = context.TreatmentStart, EndDate = context.TreatmentEnd }; var existingDisabilitiesPeriods = (await _unitOfWork.QueryAsync( (connection, transaction) => connection.QueryAsync <DateRange>(sql, hardStopQueryParameters, transaction))).ToList(); if (existingDisabilitiesPeriods.Any(t => t.Intersects(hardStopRange))) { return(new Card("Для Указанного листка нетрудоспособности существует листок с пересекающимся периодом", Indicator.HardStop, new Link(""))); } var warningRange = new DateRange() { BeginDate = context.TreatmentStart.AddDays(-(_options.LeftPeriodIncrementForWarningDays + 1)), EndDate = context.TreatmentEnd.AddDays(+(_options.LeftPeriodIncrementForWarningDays + 1)) }; if (existingDisabilitiesPeriods.Any(t => t.Intersects(warningRange))) { return(new Card("Для Указанного листка нетрудоспособности существует листок с пересекающимся периодом", Indicator.Warning, new Link(""))); } return(new Card("Правило пройдено успешно", Indicator.Success, new Link(""))); }
protected override async Task<Card> HandleCore(DisabilitySheetHookContext context) { if (context.CompositionCreating <= context.TreatmentStart) return new Card("Правило пройдено успешно", Indicator.Success, new Link("")); if (string.Equals(context.TreatmentModeCode, TreatmentModeInpatient)) { return new Card("Дата выписки листка нетрудоспособности не должна превышать дату освобождения от работы при выполнении условия - режим должен быть стационарный.", Indicator.Success, new Link("")); } if (context.VkkDates != null) { if (string.Equals(context.TreatmentModeCode, TreatmentModeMmbulatory) && context.VkkDates.Any(d => d.Date == context.CompositionCreating.Date)) { return new Card("Дата выписки листка нетрудоспособности не должна превышать дату освобождения от работы при выполнении условия - режим амбулаторный и проведено ВКК в день выписки.", Indicator.Success, new Link("")); } } return new Card("Дата выписки листка нетрудоспособности не должна превышать дату освобождения от работы", Indicator.HardStop, new Link("")); }
protected override async Task <Card> HandleCore(DisabilitySheetHookContext context) { if (_options.AvailableKindDisabilityCodes.Any( a => a.Equals(context.KindDisabilityCode, StringComparison.CurrentCultureIgnoreCase)) == false) { return(null); } //Поскольку правило звучит как Превышение периода непрерывного срока нетрудоспособности, то нужно учитывать и предидущие и последующие листки нетрудоспособности var sql = $@"SELECT eoc.start as beginDate, eoc.end as endDate, LOWER(diagnosis_code) SIMILAR TO '({string.Join("|", _options.TuberculosisMkbDiagnosis)})%' as IsTuberculosis FROM episodeofcare eoc INNER JOIN episodeofcare_condition ecc ON ecc.episodeofcare_id = eoc.id INNER JOIN condition ec ON ec.id = ecc.condition_id AND ec.status = 'final' INNER JOIN composition com ON com.episodeofcare_id = eoc.id and com.status!='entered-in-error' WHERE eoc.status!='cancelled' and com.subject_id = @PatientId and eoc.id!=@EpisodeOfCareId"; var existingDisabilitiesPeriods = (await _unitOfWork.QueryAsync( (connection, transaction) => connection.QueryAsync <ThreatmentRange>(sql, new { PatientId = context.FreedPersonId, context.EpisodeOfCareId }, transaction))).ToList(); var isTuberculosisConditioninRequest = _options.TuberculosisMkbDiagnosis.Any(t => context.DiagnosisCode.ToLowerInvariant().StartsWith(t)); existingDisabilitiesPeriods = existingDisabilitiesPeriods.Where(d => d.IsTuberculosis == isTuberculosisConditioninRequest).OrderBy(p => p.BeginDate).ToList(); var continuousDisabilitiesPeriods = new List <ThreatmentRange>(); DateTime?startDate = context.TreatmentStart; //Выбираем непрерывные переоды предшествующие while (startDate != null) { var previosPeriod = existingDisabilitiesPeriods.FirstOrDefault(p => p.EndDate <= startDate.Value && (startDate.Value - p.EndDate).TotalHours <= 24); if (previosPeriod != null) { continuousDisabilitiesPeriods.Add(previosPeriod); startDate = previosPeriod.BeginDate; continue; } startDate = null; } DateTime?endDate = context.TreatmentEnd; //Выбираем непрерывные переоды последующие while (endDate != null) { var nextPeriod = existingDisabilitiesPeriods.FirstOrDefault(p => p.BeginDate >= endDate.Value && (p.BeginDate - endDate.Value).TotalHours <= 24); if (nextPeriod != null) { continuousDisabilitiesPeriods.Add(nextPeriod); endDate = nextPeriod.EndDate; continue; } endDate = null; } continuousDisabilitiesPeriods.Add(new ThreatmentRange() { EndDate = context.TreatmentEnd, BeginDate = context.TreatmentStart, IsTuberculosis = _options.TuberculosisMkbDiagnosis.Any(d => d.Equals(context.DiagnosisCode, StringComparison.OrdinalIgnoreCase)) }); //Выбираем из списка переодов те которые граничат с текущим с разницей в день //И по критерию туберкулезности должны соответствовать контексту //var continuousDisabilitiesPeriods = existingDisabilitiesPeriods.Where( // p => (p.BeginDate - context.TreatmentStart).Hours <= TimeSpan.FromDays(1).Hours || // (p.EndDate - context.TreatmentEnd).Hours <= TimeSpan.FromDays(1).Hours).Where(d => d.IsTuberculosis == isTuberculosisConditioninRequest).ToList(); var continiousDays = continuousDisabilitiesPeriods.Sum(p => (p.EndDate - p.BeginDate).Days + 1); var maximumYearDays = isTuberculosisConditioninRequest ? _options.MaximumTuberculosisDaysCount : _options.MaximumDaysCountWithoutTuberculosis; if (continiousDays > maximumYearDays) { return(new Card("Превышение периода непрерывного срока нетрудоспособности", Indicator.HardStop, new Link(""))); } if (continiousDays >= maximumYearDays - _options.DaysPriorToExcees) { return(new Card("Превышение периода непрерывного срока нетрудоспособности", Indicator.Warning, new Link(""))); } return(new Card("Правило пройдено успешно", Indicator.Success, new Link(""))); }
protected override async Task <Card> HandleCore(DisabilitySheetHookContext context) { //Если вид нетрудоспособности не уход за больным членом семьи то правило не проверяем if (string.Equals(context.KindDisabilityCode, KindDisabilityCode) == false) { return(null); } if ((context.TreatmentEnd - context.TreatmentStart).Days + 1 > 14) { return(new Card("Больничный листок по уходу за больным членом семьи не должен превышать 14 дней", Indicator.HardStop, new Link(""))); } var sql = @" select (select EXTRACT(YEAR FROM age(cast(pat.date_birth as date))) from patient pat where pat.id = @PatientId ) as age, ( SELECT SUM(DATE_PART('day', eoc.end::timestamp - eoc.start::timestamp)+1) FROM composition com JOIN episodeofcare eoc on com.episodeofcare_id = eoc.id FULL OUTER JOIN patient pat on eoc.patient_id = pat.id where ( (com.status != 'entered-in-error' and eoc.status!='cancelled' and com.claim_id = @ClaimId) or com.claim_id is null or @ClaimId is null ) and (eoc.id!=@EpisodeOfCareId or eoc.id is null) and pat.id = @PatientId Group by pat.id ) as dayscount ; "; var sqlParameters = new { context.ClaimId, context.EpisodeOfCareId, context.PatientId }; var fromDataBase = (await _unitOfWork.QueryAsync( (connection, transaction) => connection.QuerySingleOrDefaultAsync <dynamic>(sql, sqlParameters, transaction))); //Добавляем период Eoc Пришедший в cds var duration = (context.TreatmentEnd - context.TreatmentStart).Days + 1 + (fromDataBase == null ? 0 : fromDataBase.dayscount ?? 0); if (duration > 14) { return(new Card("Больничный листок по уходу за больным членом семьи не должен превышать 14 дней", Indicator.HardStop, new Link(""))); } if (fromDataBase == null || fromDataBase?.age == null) { if (duration <= 7) { return(new Card("Правило пройдено успешно", Indicator.Success, new Link(""))); } if (duration <= 14) { return(new Card("Возраст пациента неизвестен. Больничный не может быть более 14 дней для детей до 14 лет, в остальных случаях 7 дней", Indicator.Warning, new Link(""))); } } if (fromDataBase?.age > 14) { if (context.VkkDates.Any() == false) { return(new Card("Для Выписки больничного листка пациенту, чей возраст больше 14 лет, должно быть проведено ВКК", Indicator.HardStop, new Link(""))); } if (duration > 7) { return(new Card("Больничный листок по уходу за больным членом семьи не должен превышать 7 дней", Indicator.HardStop, new Link(""))); } } return(new Card("Правило выполнено успешно", Indicator.Success, new Link(""))); }