department-of-veterans-affairs / vets-api

API powering VA.gov
https://api.va.gov
Other
207 stars 63 forks source link

Define facility locator VA health facility format #134

Closed patrickvinograd closed 8 years ago

patrickvinograd commented 8 years ago

Using this issue to come to agreement about facility locator data format. Limiting discussion for now to VA health facilities. Will file a separate issue for Choice Act provider data, and likely a separate issue for VA benefits and cemetery facilities.

See baseline data available from GIS data source in https://github.com/department-of-veterans-affairs/kudos-team/blob/master/FacilityLocator/Facility%20Data%20Samples.md See nesting discussion in #126

Here is a baseline object:

{ "attributes":
{"OBJECTID":1510,
"FacilityDataDate":"8-19-2016",
"OutpatientServicesDataDate":1472428800000,
"StationID":539,
"VisnID":20,
"StationNumber":"648A4",
"StationName":"Portland VA Medical Center-Vancouver",
"CommonStationName":"Portland-Vancouver",
"CocClassification":"VA Medical Center (VAMC)",
"CocClassificationAttribute":"Firm",
"Building":null,
"Street":"1601 East 4th Plain Boulevard",
"Suite":null,
"City":"Vancouver",
"State":"WA",
"Zip":"98661",
"Zip4":"3753",
"MainPhone":"360-759-1901 x",
"MainFax":"360-690-0864 x",
"AfterHoursPhone":"360-696-4061 x",
"PatientAdvocatePhone":"503-273-5308 x",
"EnrollmentCoordinatorPhone":"503-273-5069 x",
"PharmacyPhone":"503-273-5183 x",
"Monday":"730AM-430PM",
"Tuesday":"730AM-630PM",
"Wednesday":"730AM-430PM",
"Thursday":"730AM-430PM",
"Friday":"730AM-430PM",
"Saturday":"800AM-1000AM",
"Sunday":"-",
"Latitude":45.63941626,
"Longitude":-122.65528736,
"Audiology":"YES",
"ComplementaryAlternativeMed":"NO",
"DentalServices":"YES",
"DiagnosticServices":"YES",
"ImagingAndRadiology":"YES",
"LabServices":"NO",
"EmergencyDept":"NO",
"EyeCare":"YES",
"MentalHealthCare":"YES",
"OutpatientMHCare":"YES",
"OutpatientSpecMHCare":"YES",
"VocationalAssistance":"YES",
"OutpatientMedicalSpecialty":"NO",
"AllergyAndImmunology":"NO",
"CardiologyCareServices":"NO",
"DermatologyCareServices":"NO",
"Diabetes":"NO",
"Dialysis":"NO",
"Endocrinology":"NO",
"Gastroenterology":"NO",
"Hematology":"NO",
"InfectiousDisease":"NO",
"InternalMedicine":"NO",
"Nephrology":"NO",
"Neurology":"NO",
"Oncology":"NO",
"PulmonaryRespiratoryDisease":"NO",
"Rheumatology":"NO",
"SleepMedicine":"NO",
"OutpatientSurgicalSpecialty":"YES",
"CardiacSurgery":"NO",
"ColoRectalSurgery":"NO",
"ENT":"NO",
"GeneralSurgery":"NO",
"Gynecology":"NO",
"Neurosurgery":"NO",
"Orthopedics":"NO",
"PainManagement":"NO",
"PlasticSurgery":"NO",
"Podiatry":"YES",
"ThoracicSurgery":"NO",
"Urology":"NO",
"VascularSurgery":"NO",
"PrimaryCare":"YES",
"Rehabilitation":"YES",
"UrgentCare":"NO",
"WellnessAndPreventativeCare":"YES"
},
"geometry":{"x":-122.65530186353662,"y":45.63942173397186}
}

Proposed format is as follows:

{ 
  "id":539,
  "visn_id":20,
  "name":"Portland VA Medical Center-Vancouver",
  "classification":"VA Medical Center (VAMC)",
  "address": {
    "building":null,
    "street":"1601 East 4th Plain Boulevard",
    "suite":null,
    "city":"Vancouver",
    "state":"WA",
    "zip":"98661",
    "zip4":"3753"
  },
  "phone": {
    "main":"360-759-1901 x",
    "fax":"360-690-0864 x",
    "after_hours":"360-696-4061 x",
    "patient_advocate":"503-273-5308 x",
    "enrollment_coordinator":"503-273-5069 x",
    "pharmacy":"503-273-5183 x",
  },
  "hours": {
    "Monday":"730AM-430PM",
    "Tuesday":"730AM-630PM",
    "Wednesday":"730AM-430PM",
    "Thursday":"730AM-430PM",
    "Friday":"730AM-430PM",
    "Saturday":"800AM-1000AM",
    "Sunday":"-",
  },
  "services": {
    "Audiology": [],
    "DentalServices": [],
    "DiagnosticServices": ["ImagingAndRadiology"],
    "EyeCare": [],
    "MentalHealthCare": ["OutpatientMHCare", "OutpatientSpecMHCare", "VocationalAssistance"]
    "OutpatientSurgicalSpecialty": [],
    "PrimaryCare": [],
    "Rehabilitation": [],
    "WellnessAndPreventativeCare": []
  },
  "lat":45.63941626,
  "long":-122.65528736
}

Open issues:

patrickvinograd commented 8 years ago

We can of course iterate as needed but let me know if this looks reasonable as a starting point.

saneshark commented 8 years ago

Do we want to follow the same format of JSON API spec used elsewhere in vets-api?

http://jsonapi.org/

Note, vets-api will give the capability for F/E to automatically use whatever they want for JSON keys, whether that is camel case, snake case, etc.

patrickvinograd commented 8 years ago

I'm not opposed to using JSON API...wasn't aware that had been adopted across the board. For this API it seems like we just add a type, and push all the fields under attributes. And of course adopt the data/errors convention for the overall result.

patrickvinograd commented 8 years ago

So a collection result would look like the following, a single resource result similar without the array:

{
  "data": [
    {
    "id":539,
    "type": "va_health_facility",
    "attributes": {
      "visn_id":20,
      "name":"Portland VA Medical Center-Vancouver",
      "classification":"VA Medical Center (VAMC)",
      "address": {
        "building":null,
        "street":"1601 East 4th Plain Boulevard",
        "suite":null,
        "city":"Vancouver",
        "state":"WA",
        "zip":"98661",
        "zip4":"3753"
      },
      "phone": {
        "main":"360-759-1901 x",
        "fax":"360-690-0864 x",
        "after_hours":"360-696-4061 x",
        "patient_advocate":"503-273-5308 x",
        "enrollment_coordinator":"503-273-5069 x",
        "pharmacy":"503-273-5183 x",
      },
      "hours": {
        "Monday":"730AM-430PM",
        "Tuesday":"730AM-630PM",
        "Wednesday":"730AM-430PM",
        "Thursday":"730AM-430PM",
        "Friday":"730AM-430PM",
        "Saturday":"800AM-1000AM",
        "Sunday":"-",
      },
      "services": {
        "Audiology": [],
        "DentalServices": [],
        "DiagnosticServices": ["ImagingAndRadiology"],
        "EyeCare": [],
        "MentalHealthCare": ["OutpatientMHCare", "OutpatientSpecMHCare", "VocationalAssistance"]
        "OutpatientSurgicalSpecialty": [],
        "PrimaryCare": [],
        "Rehabilitation": [],
        "WellnessAndPreventativeCare": []
      },
      "lat":45.63941626,
      "long":-122.65528736
    }
  }
  ]
}
patrickvinograd commented 8 years ago

I don't like how Olive Branch permutes the keys but not the values of the services section, so changing this to:

{
  "data": [
    {
    "id":539,
    "type": "va_health_facility",
    "attributes": {
      "visn_id":20,
      "name":"Portland VA Medical Center-Vancouver",
      "classification":"VA Medical Center (VAMC)",
      "address": {
        "building":null,
        "street":"1601 East 4th Plain Boulevard",
        "suite":null,
        "city":"Vancouver",
        "state":"WA",
        "zip":"98661",
        "zip4":"3753"
      },
      "phone": {
        "main":"360-759-1901 x",
        "fax":"360-690-0864 x",
        "after_hours":"360-696-4061 x",
        "patient_advocate":"503-273-5308 x",
        "enrollment_coordinator":"503-273-5069 x",
        "pharmacy":"503-273-5183 x",
      },
      "hours": {
        "monday":"730AM-430PM",
        "tuesday":"730AM-630PM",
        "wednesday":"730AM-430PM",
        "thursday":"730AM-430PM",
        "friday":"730AM-430PM",
        "saturday":"800AM-1000AM",
        "sunday":"-",
      },
      "services": [
        ["Audiology",[]],
        ["DentalServices",[]],
        ["DiagnosticServices",["ImagingAndRadiology"]],
        ["EyeCare",[]],
        ["MentalHealthCare",["OutpatientMHCare","OutpatientSpecMHCare","VocationalAssistance"]],
        ["OutpatientSurgicalSpecialty",["Podiatry"]],
        ["PrimaryCare",[]],
        ["Rehabilitation",[]],
        ["WellnessAndPreventativeCare",[]] 
      ],
      "lat":45.63941626,
      "long":-122.65528736
    }
  }
  ]
}
saneshark commented 8 years ago

This looks good to me. The only thing that looks really weird is how "services" object is being built. It appears as though services are almost their own object? One of the other things we're doing is including links to additional, but relevant resources. If you use active model serializers, it should help take care of all of that for you and it kinda of adds a nice little decorator pattern should you ever need to tweak things at the presentation layer.

At some point when vets-api reaches a certain level of maturity, we should probably go in and make sure all endpoints are consistent, but I think this is a good start for now.

saneshark commented 8 years ago

Olive branch is designed to only mutate the keys, which helps for object deserialization. I think the idea is to have the values still be whatever the backend expects to validate the model (particularly if there is a POST or PUT), though I presume in your case these are mostly all just GET requests so YMMV

Again, would just err on the side of consistency.

ayaleloehr commented 8 years ago

@patrickvinograd I'm pretty sure we are going to want "Station Number" returned, as that should be the unique identifier for each facility. In the prototype we used that for the URL of the detail page, which I don't know if we still want to do or not, but could be useful.

@saneshark definitely knows JSON API better than me, especially around the active model serializer magic, so I think if where you ended up is both something that's mostly consistent with the rest of vets-api and easily consumable by the front end (which it looks like this is), then that's great. Nesting address, phone, and hours is awesome as well, great call!

patrickvinograd commented 8 years ago

@saneshark I've got it integrated with an ActiveModel Serializer in my branch, cribbing variously from the prescriptions and claims stuff in there already. I don't think it's worthwhile to pull the services out into a linked object - the list of services is definitely an attribute of the facility, it's just that there is a hierarchical structure to the services (specialties and sub-specialties).

patrickvinograd commented 8 years ago

@ayaleloehr I had confirmed that StationID was also unique, but I have no idea whether that or StationNumber is semantically more meaningful as far as the URL path identifier. I'll include both in the object and maybe I will ask Xiaoyi for details.

ayaleloehr commented 8 years ago

Just cross referenced an old document of (not totally updated but pretty good) facility data that is here and it looks like StationNumber is the things we will want.

In that document, the StationNumber for "Parsons" is 589G5 and from this query on the API the StationNumber is the same and StationID is something totally different (I don't know what StationID maps to...).

patrickvinograd commented 8 years ago

I don't even see a StationID in that spreadsheet - just an OBJECTID which is known to not be a good stable identifier (basically a rownum in the GIS database). But, it confirms that StationNumber has a semantic meaning within VA, and is also unique across facility types, so I will go with that as the primary identifier.