Skip to content

Commit 3f15f93

Browse files
fix missing mbi period for current mbis
1 parent 37fc157 commit 3f15f93

17 files changed

Lines changed: 218 additions & 269 deletions

File tree

apps/bfd-pipeline/bfd-pipeline-idr/bfd.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,17 @@ CREATE VIEW idr.beneficiary_entitlement_reason_current AS
439439
SELECT * FROM idr.beneficiary_entitlement_reason
440440
WHERE idr_ltst_trans_flg = 'Y' AND bene_rng_bgn_dt <= NOW() - INTERVAL '12 hours' AND bene_rng_end_dt >= NOW() - INTERVAL '12 hours';
441441

442+
CREATE VIEW idr.beneficiary_identity AS
443+
SELECT DISTINCT
444+
bene.bene_sk,
445+
bene.bene_xref_efctv_sk_computed,
446+
bene.bene_mbi_id,
447+
bene_mbi.bene_mbi_efctv_dt,
448+
bene_mbi.bene_mbi_obslt_dt
449+
FROM idr.beneficiary bene
450+
LEFT JOIN idr.beneficiary_mbi_id bene_mbi
451+
ON bene.bene_mbi_id = bene_mbi.bene_mbi_id;
452+
442453
CREATE OR REPLACE FUNCTION idr.refresh_overshare_mbis()
443454
RETURNS VOID AS $$
444455
DECLARE comment_sql TEXT;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
BENE_MBI_ID,BENE_MBI_EFCTV_DT,BENE_MBI_OBSLT_DT,IDR_TRANS_EFCTV_TS,IDR_INSRT_TS,IDR_UPDT_TS,IDR_TRANS_OBSLT_TS
2+
2B19C89AA35,2020-04-21,9999-12-31,2022-07-10 09:11:52.588300,2023-05-07 17:37:59.821448,9999-12-31 00:00:00.000000,9999-12-31 00:00:00.000000
3+
2B19C89AA36,2020-04-21,2024-12-31,2022-07-10 09:11:52.588300,2023-05-07 17:37:59.821448,9999-12-31 00:00:00.000000,9999-12-31 00:00:00.000000
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
BENE_SK,BENE_XREF_EFCTV_SK,BENE_XREF_SK,BENE_MBI_ID,BENE_LAST_NAME,BENE_1ST_NAME,BENE_MIDL_NAME,BENE_BRTH_DT,BENE_DEATH_DT,BENE_VRFY_DEATH_DAY_SW,BENE_SEX_CD,BENE_RACE_CD,BENE_LINE_1_ADR,BENE_LINE_2_ADR,BENE_LINE_3_ADR,BENE_LINE_4_ADR,BENE_LINE_5_ADR,BENE_LINE_6_ADR,GEO_ZIP_PLC_NAME,GEO_ZIP5_CD,GEO_USPS_STATE_CD,CNTCT_LANG_CD,IDR_TRANS_EFCTV_TS,IDR_INSRT_TS,IDR_UPDT_TS,IDR_TRANS_OBSLT_TS,IDR_LTST_TRANS_FLG
2-
878934873,178083966,178083966,9OJ2CG2UC85,Jones,Abby,,1922-04-01,,~,1,6,2904 61st,,,,,,Galveston,77551,TX,~,2024-06-04 18:32:49.034231,2024-12-10 12:27:50.972975,9999-12-31T00:00:00.000000+0000,9999-12-31 00:00:00.000000,Y
3-
792872340,178083966,178083966,9OJ2CG2UC85,Jones,Abby,,1922-04-01,,~,1,6,2904 61st,,,,,,Galveston,77551,TX,~,2024-06-04 18:32:49.034231,2024-12-10 12:27:50.972975,9999-12-31T00:00:00.000000+0000,9999-12-31 00:00:00.000000,N
42
178083966,178083966,178083966,9OJ2CG2UC85,Jones,Abby,,1922-04-01,,~,1,6,2904 61st,,,,,,Galveston,77551,TX,~,2023-09-12 01:53:35.572554,2025-04-26 14:53:59.117910,9999-12-31T00:00:00.000000+0000,9999-12-31 00:00:00.000000,Y

apps/bfd-server-ng/src/main/java/gov/cms/bfd/server/ng/beneficiary/BeneficiaryRepository.java

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import gov.cms.bfd.server.ng.DateUtil;
44
import gov.cms.bfd.server.ng.beneficiary.model.Beneficiary;
5+
import gov.cms.bfd.server.ng.beneficiary.model.BeneficiaryIdentity;
56
import gov.cms.bfd.server.ng.input.DateTimeRange;
6-
import gov.cms.bfd.server.ng.patient.PatientIdentity;
77
import jakarta.persistence.EntityManager;
88
import java.time.ZonedDateTime;
99
import java.util.List;
@@ -25,26 +25,15 @@ public class BeneficiaryRepository {
2525
* @return list of patient identities representing all active identities connected to the bene
2626
* record
2727
*/
28-
public List<PatientIdentity> getValidBeneficiaryIdentities(long beneXrefSk) {
28+
public List<BeneficiaryIdentity> getValidBeneficiaryIdentities(long beneXrefSk) {
2929
return entityManager
3030
.createQuery(
3131
"""
32-
SELECT new PatientIdentity(
33-
ROW_NUMBER() OVER (ORDER BY bene.beneSk) rowId,
34-
bene.beneSk,
35-
bene.xrefSk,
36-
bene.identity.mbi,
37-
mbiId.effectiveDate,
38-
mbiId.obsoleteDate
39-
)
40-
FROM Beneficiary bene
41-
LEFT JOIN BeneficiaryMbiId mbiId
42-
ON bene.identity.mbi = mbiId.mbi
43-
AND mbiId.obsoleteDate < gov.cms.bfd.server.ng.IdrConstants.DEFAULT_DATE
44-
WHERE bene.xrefSk = :beneXrefSk
45-
GROUP BY bene.beneSk, bene.xrefSk, bene.identity.mbi, mbiId.effectiveDate, mbiId.obsoleteDate
32+
SELECT identity
33+
FROM BeneficiaryIdentity identity
34+
WHERE identity.xrefSk = :beneXrefSk
4635
""",
47-
PatientIdentity.class)
36+
BeneficiaryIdentity.class)
4837
.setParameter("beneXrefSk", beneXrefSk)
4938
.getResultList();
5039
}
@@ -112,7 +101,7 @@ public Optional<Long> getXrefSkFromMbi(String mbi) {
112101
"""
113102
SELECT bene.xrefSk
114103
FROM Beneficiary bene
115-
WHERE bene.identity.mbi = :mbi
104+
WHERE bene.identifier.mbi = :mbi
116105
""",
117106
Long.class)
118107
.setParameter("mbi", mbi)

apps/bfd-server-ng/src/main/java/gov/cms/bfd/server/ng/beneficiary/model/BeneficiaryBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public abstract class BeneficiaryBase {
4242
@Embedded protected Address address;
4343
@Embedded protected Meta meta;
4444
@Embedded protected DeathDate deathDate;
45-
@Embedded protected Identity identity;
45+
@Embedded protected CurrentIdentifier identifier;
4646

4747
/**
4848
* Determines if this beneficiary has been merged into another.

apps/bfd-server-ng/src/main/java/gov/cms/bfd/server/ng/patient/PatientIdentity.java renamed to apps/bfd-server-ng/src/main/java/gov/cms/bfd/server/ng/beneficiary/model/BeneficiaryIdentity.java

Lines changed: 37 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,43 @@
1-
package gov.cms.bfd.server.ng.patient;
1+
package gov.cms.bfd.server.ng.beneficiary.model;
22

33
import gov.cms.bfd.server.ng.DateUtil;
4+
import gov.cms.bfd.server.ng.IdrConstants;
45
import gov.cms.bfd.server.ng.SystemUrls;
6+
import jakarta.persistence.Column;
57
import jakarta.persistence.Entity;
68
import jakarta.persistence.Id;
9+
import jakarta.persistence.Table;
710
import java.time.LocalDate;
811
import java.util.List;
912
import java.util.Optional;
13+
import lombok.Getter;
1014
import org.hl7.fhir.r4.model.CodeableConcept;
1115
import org.hl7.fhir.r4.model.Coding;
1216
import org.hl7.fhir.r4.model.Identifier;
1317
import org.hl7.fhir.r4.model.Patient;
1418
import org.hl7.fhir.r4.model.Period;
1519
import org.hl7.fhir.r4.model.Reference;
1620

17-
/**
18-
* A projection type created by joining the beneficiary, beneficiary_history, and
19-
* beneficiary_mbi_history tables.
20-
*
21-
* <p>This does not actually represent a table in the database, but we use the {@link Entity}
22-
* attribute here so it can be used in JPA queries and have converters applied to its fields.
23-
*/
21+
/** The beneficiary_identity view, for getting current and historical bene_sks and MBIs. */
22+
@Getter
23+
@Table(name = "beneficiary_identity", schema = "idr")
2424
@Entity
25-
public class PatientIdentity {
26-
// The id field is not actually used here, but JPA requires some unique ID for every entity, even
27-
// if it's just used for joins.
28-
// Ideally, we could use beneSk + mbi, but this becomes tricky because MBI may not always be
29-
// present.
30-
@Id Long rowId;
31-
String beneSk;
32-
String xrefSk;
33-
Optional<String> mbi;
34-
Optional<LocalDate> mbiEffectiveDate;
35-
Optional<LocalDate> mbiObsoleteDate;
25+
public class BeneficiaryIdentity {
26+
@Id
27+
@Column(name = "bene_sk")
28+
protected long beneSk;
3629

37-
/**
38-
* Creates a new Identity record.
39-
*
40-
* @param rowId row ID from the query that created this object
41-
* @param beneSk bene_sk from the database
42-
* @param xrefSk bene_xref_sk from the database
43-
* @param mbi MBI from the database
44-
* @param mbiEffectiveDate MBI effective date
45-
* @param mbiObsoleteDate MBI obsolete date
46-
*/
47-
public PatientIdentity(
48-
Long rowId,
49-
Long beneSk,
50-
Long xrefSk,
51-
String mbi,
52-
Optional<LocalDate> mbiEffectiveDate,
53-
Optional<LocalDate> mbiObsoleteDate) {
54-
this.rowId = rowId;
55-
this.beneSk = beneSk.toString();
56-
this.xrefSk = xrefSk.toString();
57-
this.mbi = Optional.ofNullable(mbi);
58-
this.mbiEffectiveDate = mbiEffectiveDate;
59-
this.mbiObsoleteDate = mbiObsoleteDate;
60-
}
30+
@Column(name = "bene_mbi_id")
31+
private Optional<String> mbi;
32+
33+
@Column(name = "bene_xref_efctv_sk_computed")
34+
private long xrefSk;
35+
36+
@Column(name = "bene_mbi_efctv_dt")
37+
private Optional<LocalDate> mbiEffectiveDate;
38+
39+
@Column(name = "bene_mbi_obslt_dt")
40+
private Optional<LocalDate> mbiObsoleteDate;
6141

6242
/**
6343
* Transforms the identity record to a FHIR {@link Identifier} if a valid MBI is present.
@@ -69,12 +49,18 @@ public Optional<Identifier> toFhirIdentifier() {
6949
return Optional.empty();
7050
}
7151
var identifier = new Identifier().setSystem(SystemUrls.CMS_MBI).setValue(mbi.get());
52+
var period = new Period();
7253
mbiEffectiveDate.ifPresent(
7354
e -> {
74-
var period = new Period().setStart(DateUtil.toDate(e));
75-
mbiObsoleteDate.ifPresent(o -> period.setEnd(DateUtil.toDate(o)));
76-
identifier.setPeriod(period);
55+
period.setStart(DateUtil.toDate(e));
56+
});
57+
mbiObsoleteDate.ifPresent(
58+
o -> {
59+
if (o.isBefore(IdrConstants.DEFAULT_DATE)) {
60+
period.setEnd(DateUtil.toDate(o));
61+
}
7762
});
63+
identifier.setPeriod(period);
7864

7965
final var memberNumber = "MB";
8066
var mbiCoding =
@@ -93,11 +79,11 @@ public Optional<Identifier> toFhirIdentifier() {
9379
* @param requestedBeneSk bene_sk value for the beneficiary that was requested
9480
* @return patient link
9581
*/
96-
public Optional<Patient.PatientLinkComponent> toFhirLink(String requestedBeneSk) {
82+
public Optional<Patient.PatientLinkComponent> toFhirLink(long requestedBeneSk) {
9783

98-
var beneSkMatches = beneSk.equals(requestedBeneSk);
99-
var currentIsXref = xrefSk.equals(beneSk);
100-
var requestedIsXref = xrefSk.equals(requestedBeneSk);
84+
var beneSkMatches = beneSk == requestedBeneSk;
85+
var currentIsXref = xrefSk == beneSk;
86+
var requestedIsXref = xrefSk == requestedBeneSk;
10187

10288
// This identity record is the current xref record and it has a different bene_sk, so the
10389
// requested bene_sk is replaced by this one
@@ -119,7 +105,7 @@ private Patient.PatientLinkComponent createLink(Patient.LinkType linkType) {
119105
link.setType(linkType);
120106
var reference = new Reference();
121107
reference.setReference("Patient/" + beneSk);
122-
reference.setDisplay(beneSk);
108+
reference.setDisplay(String.valueOf(beneSk));
123109
link.setOther(reference);
124110
return link;
125111
}

apps/bfd-server-ng/src/main/java/gov/cms/bfd/server/ng/beneficiary/model/BeneficiaryMbiId.java

Lines changed: 0 additions & 23 deletions
This file was deleted.

apps/bfd-server-ng/src/main/java/gov/cms/bfd/server/ng/beneficiary/model/Identity.java renamed to apps/bfd-server-ng/src/main/java/gov/cms/bfd/server/ng/beneficiary/model/CurrentIdentifier.java

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import lombok.NoArgsConstructor;
1010
import org.hl7.fhir.r4.model.CodeableConcept;
1111
import org.hl7.fhir.r4.model.Coding;
12-
import org.hl7.fhir.r4.model.Identifier;
1312

1413
/**
1514
* Represents the beneficiary's primary identity information (specifically MBI) as relevant for
@@ -20,25 +19,25 @@
2019
@Getter
2120
@AllArgsConstructor
2221
@NoArgsConstructor
23-
public class Identity {
22+
public class CurrentIdentifier {
2423

2524
@Column(name = "bene_mbi_id")
2625
private String mbi;
2726

2827
/**
29-
* Transforms this identity information into a FHIR {@link Identifier} for the MBI. This
30-
* identifier does not include a period, as it represents the beneficiary's primary MBI in the
31-
* context of the Coverage resource.
28+
* Transforms this identity information into a FHIR {@link org.hl7.fhir.r4.model.Identifier} for
29+
* the MBI. This identifier does not include a period, as it represents the beneficiary's primary
30+
* MBI in the context of the Coverage resource.
3231
*
33-
* @return An {@link Optional} containing the FHIR {@link Identifier} if an MBI is present,
34-
* otherwise {@link Optional#empty()}.
32+
* @return An {@link Optional} containing the FHIR {@link org.hl7.fhir.r4.model.Identifier} if an
33+
* MBI is present, otherwise {@link Optional#empty()}.
3534
*/
36-
public Optional<Identifier> toFhirMbiIdentifier() {
35+
public Optional<org.hl7.fhir.r4.model.Identifier> toFhir() {
3736
if (mbi.isEmpty()) {
3837
return Optional.empty();
3938
}
4039

41-
Identifier mbiIdentifier = new Identifier();
40+
org.hl7.fhir.r4.model.Identifier mbiIdentifier = new org.hl7.fhir.r4.model.Identifier();
4241
mbiIdentifier.setType(
4342
new CodeableConcept()
4443
.addCoding(
@@ -51,13 +50,4 @@ public Optional<Identifier> toFhirMbiIdentifier() {
5150

5251
return Optional.of(mbiIdentifier);
5352
}
54-
55-
/**
56-
* Gets the MBI string, if present.
57-
*
58-
* @return An {@link Optional} containing the MBI string.
59-
*/
60-
public String getMbiValue() {
61-
return mbi;
62-
}
6353
}

apps/bfd-server-ng/src/main/java/gov/cms/bfd/server/ng/coverage/model/BeneficiaryCoverage.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ public Coverage toFhir(CoverageCompositeId coverageCompositeId) {
8282

8383
coverage.addPayor(new Reference().setReference("#" + cmsOrg.getIdElement().getIdPart()));
8484

85-
identity.toFhirMbiIdentifier().ifPresent(coverage::addIdentifier);
86-
coverage.setSubscriberId(identity.getMbiValue());
85+
identifier.toFhir().ifPresent(coverage::addIdentifier);
86+
coverage.setSubscriberId(identifier.getMbi());
8787

8888
coverage.setType(coveragePart.toFhirTypeCode());
8989
coverage.addClass_(coveragePart.toFhirClassComponent());

apps/bfd-server-ng/src/main/java/gov/cms/bfd/server/ng/patient/PatientHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ private Patient toFhir(Beneficiary beneficiary) {
6868
// check for merged bene and if mbi identifier has already been added to the patient
6969
if (!beneficiary.isMergedBeneficiary()
7070
&& patient.getIdentifier().stream()
71-
.noneMatch(identifier -> identifier.getValue().equals(id.mbi.orElse(null)))) {
71+
.noneMatch(identifier -> identifier.getValue().equals(id.getMbi().orElse("")))) {
7272
id.toFhirIdentifier().ifPresent(patient::addIdentifier);
7373
}
7474

75-
id.toFhirLink(patient.getId()).ifPresent(patient::addLink);
75+
id.toFhirLink(Long.parseLong(patient.getId())).ifPresent(patient::addLink);
7676
}
7777

7878
return patient;

0 commit comments

Comments
 (0)