From 734389a819ceb0fbd05b970b476f02fd612a22cf Mon Sep 17 00:00:00 2001 From: Anton Ivanov Date: Fri, 6 Sep 2024 11:42:09 +0300 Subject: [PATCH 1/3] added cost --- .../Transformation/CDM/Definitions/Cost.xml | 71 ++++++++++++++++ .../org.ohdsi.cdm.framework.etl.csproj | 4 + .../Common/Base/IPersonBuilder.cs | 2 + .../Common/Base/PersonBuilder.cs | 5 ++ .../Common/Definitions/CostRawDefinition.cs | 80 +++++++++++++++++++ .../Common/Definitions/QueryDefinition.cs | 7 ++ .../Base/LambdaChunkPart.cs | 10 +++ 7 files changed, 179 insertions(+) create mode 100644 sources/Framework/org.ohdsi.cdm.framework.etl/Transformation/CDM/Definitions/Cost.xml create mode 100644 sources/Framework/org.ohdsi.cdm.framework/Common/Definitions/CostRawDefinition.cs diff --git a/sources/Framework/org.ohdsi.cdm.framework.etl/Transformation/CDM/Definitions/Cost.xml b/sources/Framework/org.ohdsi.cdm.framework.etl/Transformation/CDM/Definitions/Cost.xml new file mode 100644 index 00000000..e6f43a95 --- /dev/null +++ b/sources/Framework/org.ohdsi.cdm.framework.etl/Transformation/CDM/Definitions/Cost.xml @@ -0,0 +1,71 @@ + + + SELECT cost_id + , cost_event_id + , cost_domain_id + , cost_type_concept_id + , currency_concept_id + , total_charge + , total_cost + , total_paid + + , paid_by_payer + , paid_by_patient + , paid_patient_copay + , paid_patient_coinsurance + , paid_patient_deductible + , paid_by_primary + , paid_ingredient_cost + , paid_dispensing_fee + + , payer_plan_period_id + + , amount_allowed + , revenue_code_concept_id + , revenue_code_source_value + , drg_concept_id + , drg_source_value + , coalesce(po.person_id, o.person_id, d.person_id, dev.person_id, m.person_id, v.person_id) person_id + FROM {sc}.cost + left join {sc}.procedure_occurrence po on cost_domain_id = 'Procedure' and cost_event_id = po.procedure_occurrence_id + left join {sc}.observation o on cost_domain_id = 'Observation' and cost_event_id = o.observation_id + left join {sc}.drug_exposure d on cost_domain_id = 'Drug' and cost_event_id = d.drug_exposure_id + left join {sc}.device_exposure dev on cost_domain_id = 'Device' and cost_event_id = dev.device_exposure_id + left join {sc}.measurement m on cost_domain_id = 'Measurement' and cost_event_id = m.measurement_id + left join {sc}.visit_occurrence v on cost_domain_id = 'Visit' and cost_event_id = v.visit_occurrence_id + JOIN {ch_sc}._chunks ch ON ch.ChunkId = {0} AND coalesce(po.person_id, o.person_id, d.person_id, dev.person_id, m.person_id, v.person_id) = ch.PERSON_ID + order by 1 + + + + person_id + + cost_id + cost_event_id + cost_domain_id + cost_type_concept_id + currency_concept_id + total_charge + total_cost + total_paid + + paid_by_payer + paid_by_patient + paid_patient_copay + paid_patient_coinsurance + paid_patient_deductible + paid_ingredient_cost + paid_dispensing_fee + + payer_plan_period_id + + amount_allowed + + revenue_code_concept_id + revenue_code_source_value + + drg_concept_id + drg_source_value + + + \ No newline at end of file diff --git a/sources/Framework/org.ohdsi.cdm.framework.etl/org.ohdsi.cdm.framework.etl.csproj b/sources/Framework/org.ohdsi.cdm.framework.etl/org.ohdsi.cdm.framework.etl.csproj index 8718cdac..fec42719 100644 --- a/sources/Framework/org.ohdsi.cdm.framework.etl/org.ohdsi.cdm.framework.etl.csproj +++ b/sources/Framework/org.ohdsi.cdm.framework.etl/org.ohdsi.cdm.framework.etl.csproj @@ -10,6 +10,7 @@ + @@ -303,6 +304,9 @@ Always + + Always + Always diff --git a/sources/Framework/org.ohdsi.cdm.framework/Common/Base/IPersonBuilder.cs b/sources/Framework/org.ohdsi.cdm.framework/Common/Base/IPersonBuilder.cs index fd39b1ed..153cd4b5 100644 --- a/sources/Framework/org.ohdsi.cdm.framework/Common/Base/IPersonBuilder.cs +++ b/sources/Framework/org.ohdsi.cdm.framework/Common/Base/IPersonBuilder.cs @@ -30,6 +30,8 @@ public interface IPersonBuilder void AddObservationPeriod(EraEntity data); + void AddCost(Cost data); + //void Build(ChunkData chunkData); Attrition Build(ChunkData data, KeyMasterOffsetManager offset); diff --git a/sources/Framework/org.ohdsi.cdm.framework/Common/Base/PersonBuilder.cs b/sources/Framework/org.ohdsi.cdm.framework/Common/Base/PersonBuilder.cs index 1b775f27..47a498bd 100644 --- a/sources/Framework/org.ohdsi.cdm.framework/Common/Base/PersonBuilder.cs +++ b/sources/Framework/org.ohdsi.cdm.framework/Common/Base/PersonBuilder.cs @@ -239,6 +239,11 @@ protected virtual bool AddCost(long eventId, Func createCost, IEn return ChunkData.AddCostData(cost); } + public void AddCost(Cost data) + { + ChunkData.AddCostData(data); + } + public ChunkData Result => ChunkData; public bool Complete { get; set; } diff --git a/sources/Framework/org.ohdsi.cdm.framework/Common/Definitions/CostRawDefinition.cs b/sources/Framework/org.ohdsi.cdm.framework/Common/Definitions/CostRawDefinition.cs new file mode 100644 index 00000000..e5b6c135 --- /dev/null +++ b/sources/Framework/org.ohdsi.cdm.framework/Common/Definitions/CostRawDefinition.cs @@ -0,0 +1,80 @@ +using org.ohdsi.cdm.framework.common.Builder; +using org.ohdsi.cdm.framework.common.Extensions; +using org.ohdsi.cdm.framework.common.Omop; +using System.Data; + +namespace org.ohdsi.cdm.framework.common.Definitions +{ + public class CostRawDefinition : EntityDefinition + { + public string TypeConceptId { get; set; } + + public string EventId { get; set; } + public string DomainId { get; set; } + public string CurrencyConceptId { get; set; } + public string TotalCharge { get; set; } + public string TotalCost { get; set; } + public string TotalPaid { get; set; } + + + public string PaidByPayer { get; set; } + public string PaidByPatient { get; set; } + public string PaidPatientCopay { get; set; } + public string PaidPatientCoinsurance { get; set; } + public string PaidPatientDeductible { get; set; } + public string PaidIngredientCost { get; set; } + public string PaidDispensingFee { get; set; } + + public string PayerPlanPeriodId { get; set; } + + public string AmountAllowed { get; set; } + + public string RevenueCodeConceptId { get; set; } + public string RevenueCodeSourceValue { get; set; } + + public string DrgConceptId { get; set; } + public string DrgSourceValue { get; set; } + + + public IEnumerable GetCost(Concept concept, IDataRecord reader, + KeyMasterOffsetManager offset) + { + var presonId = reader.GetLong(PersonId); + yield return new Cost(presonId.Value) + { + PersonId = presonId.Value, + TypeId = reader.GetLong(TypeConceptId), + CostId = reader.GetLong(Id) ?? 0, + EventId = reader.GetLong(EventId) ?? 0, + Domain = reader.GetString(DomainId), + CurrencyConceptId = reader.GetLong(CurrencyConceptId) ?? 0, + TotalCharge = reader.GetDecimal(TotalCharge), + TotalCost = reader.GetDecimal(TotalCost), + TotalPaid = reader.GetDecimal(TotalPaid), + + PaidByPayer = reader.GetDecimal(PaidByPayer), + PaidByPatient = reader.GetDecimal(PaidByPatient), + PaidPatientCopay = reader.GetDecimal(PaidPatientCopay), + PaidPatientCoinsurance = reader.GetDecimal(PaidPatientCoinsurance), + PaidPatientDeductible = reader.GetDecimal(PaidPatientDeductible), + PaidIngredientCost = reader.GetDecimal(PaidIngredientCost), + PaidDispensingFee = reader.GetDecimal(PaidDispensingFee), + + PayerPlanPeriodId = reader.GetLong(PayerPlanPeriodId), + + AmountAllowed = reader.GetDecimal(AmountAllowed), + + RevenueCodeConceptId = reader.GetLong(RevenueCodeConceptId), + RevenueCodeSourceValue = reader.GetString(RevenueCodeSourceValue), + + DrgConceptId = reader.GetLong(DrgConceptId), + DrgSourceValue = reader.GetString(DrgSourceValue) + }; + } + + public override IEnumerable GetConcepts(Concept concept, IDataRecord reader, KeyMasterOffsetManager offset) + { + throw new NotImplementedException("CostDefinitionRaw.GetConcepts()"); + } + } +} diff --git a/sources/Framework/org.ohdsi.cdm.framework/Common/Definitions/QueryDefinition.cs b/sources/Framework/org.ohdsi.cdm.framework/Common/Definitions/QueryDefinition.cs index 818c9793..83790c86 100644 --- a/sources/Framework/org.ohdsi.cdm.framework/Common/Definitions/QueryDefinition.cs +++ b/sources/Framework/org.ohdsi.cdm.framework/Common/Definitions/QueryDefinition.cs @@ -92,6 +92,8 @@ public class QueryDefinition public EpisodeEventDefinition[] EpisodeEvents { get; set; } public ObservationPeriodDefinition[] ObservationPeriods { get; set; } + public CostRawDefinition[] Costs { get; set; } + private static readonly string[] separator = [","]; public void RowProcessed() @@ -261,6 +263,11 @@ public string GetPersonIdFieldName() return ObservationPeriods[0].PersonId; } + if (Costs != null && Costs.Length != 0) + { + return Costs[0].PersonId; + } + throw new Exception("Cant find PersonId FieldName " + this.FileName); } } diff --git a/sources/Presentation/org.ohdsi.cdm.presentation.lambdabuilder/Base/LambdaChunkPart.cs b/sources/Presentation/org.ohdsi.cdm.presentation.lambdabuilder/Base/LambdaChunkPart.cs index 6abae411..db991e46 100644 --- a/sources/Presentation/org.ohdsi.cdm.presentation.lambdabuilder/Base/LambdaChunkPart.cs +++ b/sources/Presentation/org.ohdsi.cdm.presentation.lambdabuilder/Base/LambdaChunkPart.cs @@ -322,6 +322,7 @@ private void Watchdog_Elapsed(object sender, System.Timers.ElapsedEventArgs e) AddEntity(qd, qd.Note, reader, recordGuid, personIdsToSave); AddEntity(qd, qd.Episodes, reader, recordGuid, personIdsToSave); AddEntity(qd, qd.ObservationPeriods, reader, recordGuid, personIdsToSave); + AddEntity(qd, qd.Costs, reader, recordGuid, personIdsToSave); if (reader.Paused) break; @@ -650,6 +651,15 @@ private void AddEntity(QueryDefinition queryDefinition, IEnumerable Date: Fri, 6 Sep 2024 14:04:56 +0300 Subject: [PATCH 2/3] fixes --- .../Transformation/CDM/CdmPersonBuilder.cs | 2 ++ .../Common/Base/PersonBuilder.cs | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sources/Framework/org.ohdsi.cdm.framework.etl/Transformation/CDM/CdmPersonBuilder.cs b/sources/Framework/org.ohdsi.cdm.framework.etl/Transformation/CDM/CdmPersonBuilder.cs index da4654be..b4ca2ba4 100644 --- a/sources/Framework/org.ohdsi.cdm.framework.etl/Transformation/CDM/CdmPersonBuilder.cs +++ b/sources/Framework/org.ohdsi.cdm.framework.etl/Transformation/CDM/CdmPersonBuilder.cs @@ -228,6 +228,8 @@ public override Attrition Build(ChunkData data, KeyMasterOffsetManager o) [.. conditionOccurrences], [.. procedureOccurrences], [.. observations], [.. measurements], [.. visitOccurrences.Values], [.. visitDetails], null, [.. deviceExposure], null, null); + foreach (var c in CostRaw) + ChunkData.AddCostData(c); Complete = true; diff --git a/sources/Framework/org.ohdsi.cdm.framework/Common/Base/PersonBuilder.cs b/sources/Framework/org.ohdsi.cdm.framework/Common/Base/PersonBuilder.cs index 47a498bd..412a30aa 100644 --- a/sources/Framework/org.ohdsi.cdm.framework/Common/Base/PersonBuilder.cs +++ b/sources/Framework/org.ohdsi.cdm.framework/Common/Base/PersonBuilder.cs @@ -35,6 +35,8 @@ public class PersonBuilder : IPersonBuilder protected List DeviceExposureRaw = []; protected List DeviceCostRaw = []; + protected List CostRaw = []; + protected List DrugForEra = []; protected List ConditionForEra = []; protected List NoteRecords = []; @@ -226,6 +228,9 @@ public void Reset() EpisodeRecords.Clear(); EpisodeRecords = null; + + CostRaw.Clear(); + CostRaw = null; } protected virtual bool AddCost(long eventId, Func createCost, IEntity entity, ICostV5 entityCost) @@ -241,7 +246,7 @@ protected virtual bool AddCost(long eventId, Func createCost, IEn public void AddCost(Cost data) { - ChunkData.AddCostData(data); + CostRaw.Add(data); } public ChunkData Result => ChunkData; @@ -927,6 +932,9 @@ public virtual Attrition Build(ChunkData data, KeyMasterOffsetManager o) AddToChunk(person, death, observationPeriods, payerPlanPeriods, drugExposures, conditionOccurrences, procedureOccurrences, observations, measurements, [.. visitOccurrences.Values], visitDetails, cohort, deviceExposure, notes, episode); + + foreach(var c in CostRaw) + ChunkData.AddCostData(c); Complete = true; From 4b709f82fa200268272ab1acda1cce78d5a3fd13 Mon Sep 17 00:00:00 2001 From: Anton Ivanov Date: Fri, 6 Sep 2024 16:03:41 +0300 Subject: [PATCH 3/3] fixes --- .../DataReaders/v5/v52/CostDataReader52.cs | 36 +++++++++++++++---- .../Common/Definitions/CostRawDefinition.cs | 4 ++- .../Common/Omop/Cost.cs | 5 ++- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/sources/Framework/org.ohdsi.cdm.framework/Common/DataReaders/v5/v52/CostDataReader52.cs b/sources/Framework/org.ohdsi.cdm.framework/Common/DataReaders/v5/v52/CostDataReader52.cs index 64aad1c3..61a11e20 100644 --- a/sources/Framework/org.ohdsi.cdm.framework/Common/DataReaders/v5/v52/CostDataReader52.cs +++ b/sources/Framework/org.ohdsi.cdm.framework/Common/DataReaders/v5/v52/CostDataReader52.cs @@ -27,17 +27,41 @@ public object GetValue(int i) switch (i) { case 0: + { + if (_enumerator.Current.Id.HasValue) + return _enumerator.Current.Id.Value; - return _offset.GetId(_enumerator.Current.PersonId, - _enumerator.Current.CostId); //TODO VisitCostOffset -> CostOffset + return _offset.GetId(_enumerator.Current.PersonId, _enumerator.Current.CostId); + } case 1: + { + if (_enumerator.Current.Domain == "Procedure" && !_offset + .GetKeyOffset(_enumerator.Current.PersonId).ProcedureOccurrenceIdChanged) + return _enumerator.Current.EventId; - if (_enumerator.Current.Domain == "Visit" && !_offset - .GetKeyOffset(_enumerator.Current.PersonId).VisitOccurrenceIdChanged) - return _enumerator.Current.EventId; + if (_enumerator.Current.Domain == "Observation" && !_offset + .GetKeyOffset(_enumerator.Current.PersonId).ObservationIdChanged) + return _enumerator.Current.EventId; - return _offset.GetId(_enumerator.Current.PersonId, _enumerator.Current.EventId); + if (_enumerator.Current.Domain == "Drug" && !_offset + .GetKeyOffset(_enumerator.Current.PersonId).DrugExposureIdChanged) + return _enumerator.Current.EventId; + + if (_enumerator.Current.Domain == "Device" && !_offset + .GetKeyOffset(_enumerator.Current.PersonId).DeviceExposureIdChanged) + return _enumerator.Current.EventId; + + if (_enumerator.Current.Domain == "Measurement" && !_offset + .GetKeyOffset(_enumerator.Current.PersonId).MeasurementIdChanged) + return _enumerator.Current.EventId; + + if (_enumerator.Current.Domain == "Visit" && !_offset + .GetKeyOffset(_enumerator.Current.PersonId).VisitOccurrenceIdChanged) + return _enumerator.Current.EventId; + + return _offset.GetId(_enumerator.Current.PersonId, _enumerator.Current.EventId); + } case 2: return _enumerator.Current.Domain; diff --git a/sources/Framework/org.ohdsi.cdm.framework/Common/Definitions/CostRawDefinition.cs b/sources/Framework/org.ohdsi.cdm.framework/Common/Definitions/CostRawDefinition.cs index e5b6c135..cab4b443 100644 --- a/sources/Framework/org.ohdsi.cdm.framework/Common/Definitions/CostRawDefinition.cs +++ b/sources/Framework/org.ohdsi.cdm.framework/Common/Definitions/CostRawDefinition.cs @@ -42,9 +42,11 @@ public IEnumerable GetCost(Concept concept, IDataRecord reader, var presonId = reader.GetLong(PersonId); yield return new Cost(presonId.Value) { + Id = reader.GetLong(Id), + PersonId = presonId.Value, TypeId = reader.GetLong(TypeConceptId), - CostId = reader.GetLong(Id) ?? 0, + EventId = reader.GetLong(EventId) ?? 0, Domain = reader.GetString(DomainId), CurrencyConceptId = reader.GetLong(CurrencyConceptId) ?? 0, diff --git a/sources/Framework/org.ohdsi.cdm.framework/Common/Omop/Cost.cs b/sources/Framework/org.ohdsi.cdm.framework/Common/Omop/Cost.cs index 31c014f0..61884674 100644 --- a/sources/Framework/org.ohdsi.cdm.framework/Common/Omop/Cost.cs +++ b/sources/Framework/org.ohdsi.cdm.framework/Common/Omop/Cost.cs @@ -2,9 +2,12 @@ { public class Cost(long personId) { + public long? Id { get; set; } + public long CostId { get; set; } + public long PersonId { get; set; } = personId; public string Domain { get; set; } - public long CostId { get; set; } + public long EventId { get; set; } public long? TypeId { get; set; }