Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Our Parks #111

Closed
philjackson opened this issue Mar 9, 2018 · 12 comments
Closed

Our Parks #111

philjackson opened this issue Mar 9, 2018 · 12 comments
Labels
example Example JSON from an implementation

Comments

@philjackson
Copy link

Our Parks have started implementation:

http://35.176.129.234/api/getSessions/9210
http://35.176.129.234/api/orders/52195

@philjackson
Copy link
Author

philjackson commented Mar 9, 2018

Hey, brilliant, this is really close. My - only minor - suggestions are below. I'd like to prefix this with the fact some of these are probably my fault for not getting them right in the document we shared with you!

On the name getSessions - I'd recommend something more REST-y for this, getSessions sounds like an RPC call, perhaps /events? Nick produced this brilliant guideline doc that's really helpful for this stuff.

Session

  • Duration (on top level event) is recommended by the spec and consumers will presumably demand it. E.G "duration": "PT90M".
  • description should be plain text, to put markedup output into the document, we'd recommend beta:formattedDescription, and you can remove descriptionFormat, so:
{
  "description": "This is a description.",
  "beta:formattedDescription": "<p>This is a description.</p>"
}
  • There's a rogue postcode within the event (there should only be one in the address, which you also have).
  • eventLogo should be called image.
  • eventStatus should be one of the enumeration values mentioned here. For example, where you have active, you'd want http://schema.org/EventScheduled. So:
{ "eventStatus": "http://schema.org/EventScheduled" }
  • sameAs expects a URL, looks like you just have some sort of username there? To be honest it's an odd field, but example usage might be "sameAs": [ "https://twitter.com/edinjoy"].
  • The Organizer property should be named organizer

Orders

The /orders endpoint currently returns an error for me.

getSessions/

I was expecting this to return a paged list of events, perhaps not implemented yet.

@nickevansuk
Copy link
Contributor

nickevansuk commented Mar 9, 2018

An additional point from me: do you have Latitude and Longitude coordinates stored for each of the parks?

If so it would be really good to include that too as follows, within the location:

          "geo": {
            "type": "GeoCoordinates",
            "latitude": 51.4961, 
            "longitude": -0.024559
          }

This would tick all the boxes for OurParks on the status dashboard: https://status.openactive.io/

@nickopris
Copy link

We don't have Latitude and Longitude coordinates. We plan to add them in the future.

@nickevansuk
Copy link
Contributor

nickevansuk commented Mar 11, 2018

Something else that has just come up for "location".

For the case where City = London, could we set:

  • "addressLocality" = Borough name
  • "addressRegion" = "London" or "Greater London" depending on if a central or outer borough

Otherwise just use:

  • "addressLocality" = City
  • "addressRegion" = County

Might be easier to do this by updating the data rather than in the code?

@civsiv
Copy link

civsiv commented Mar 15, 2018

Hi, Civ from imin.
I was wondering whether there will be any differentiation between your free sessions and your premium sessions in the session details page? If they appear in the feed, then I assume anyone (not just members) could book them with a cost of £0.

@nickopris
Copy link

We are not sending Premium sessions to the feed.

@civsiv
Copy link

civsiv commented Mar 16, 2018

Ah great! Are you also not sending them to your open data feed? Or if you are, is there any way of differentiating them there too?

@nickopris
Copy link

I will check with Tudor but we should not send you any of the Premium classes in any feed. Also we need to make sure we are not accepting booking if by mistake you send a request for a Premium class.

@civsiv
Copy link

civsiv commented Mar 21, 2018

Perfect, thanks!

@civsiv
Copy link

civsiv commented Mar 21, 2018

I've just tested the /orders POST endpoint (which now works! :D ) with the body:

{
  "type": "Order",
  "broker":{
    "type":"Organisation",
    "name":"Imin"
  },
  "orderedItem": {
    "type": "OrderItem",
    "acceptedOffer":"https://ourparks.org.uk/getSessions/9210#offer",
    "orderQuantity": 1
  },
  "customer":{
    "type":"Person",
    "givenName":"Civ",
    "familyName":"Sivakumaran",
    "email":"civ@imin.co"	
  }
}

and get the following response:

{
	"type": "Order",
	"id": "https://www.ourparks.org.uk/orders/52195",
	"identifier": "52195",
	"orderedItem": {
		"type": "OrderItem",
		"acceptedOffer": "http://ourparks.org.uk/9311#offer",
		"orderQuantity": 1
	},
	"orderDate": "2018 - 03 - 08T11:33:30",
	"orderStatus": "OrderDelivered",
	"confirmationNumber": "ON9311-52195"
}
  1. As all the events that will be coming from your feed will cost £0, your feed can be considered 'entirely free'. Because of this, the order status at the lease stage (POST to /orders) should go to 'EmailValidationRequired' not 'OrderDelivered'.
  2. The orderedItem object must contain another orderedItem object inside it, which returns the sessionDetails object.
  3. The confirmation number and orderStatus of 'OrderDelivered' are only applied to the order following the successful request to PATCH /orders with the body specified in the Booking Specification.

@civsiv
Copy link

civsiv commented Mar 28, 2018

@nickopris Any update on the above? Also we were notified by one of our consumers that they could find sessions on your website that weren’t available from our API (https://ourparks.org.uk/borough/bootcamp-49898), but when we checked we couldn’t find these in your data feed. Could you look into this to see whether sessions are somehow being missed?

@nickevansuk
Copy link
Contributor

nickevansuk commented Mar 30, 2020

Here's a mapping from the current Our Parks feed to Modelling Opportunity Data specification (including considerations for virtual events):

{
  "next": "https://ourparks.org.uk/getSessions?afterTimestamp=1413138236&afterId=195", // note must be absolute URL
  "items": [
    {
      "state": "updated",
      "kind": "Event", // note must be "Event"
      "id": 96, // note must be integer
      "modified": 1397806729, // note must be integer, the library will do this
      "data": {
        "@context": [
          "https://openactive.io/",
          "https://openactive.io/ns-beta"
        ],
        "@type": "Event",
        "identifier": 96, // id (as integer)
        "eventAttendanceMode": "https://schema.org/OnlineEventAttendanceMode", // use for virtual classes
        // "eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode", // use for real classes
        "beta:isInteractivityPreferred": true, // Hard coded (check with Born?) - do all instructors prefer participants to use webcams if they are comfortable doing so?
        "beta:participantSuppliedEquipment": "https://openactive.io/Unavailable", // Hard coded (check with Born?), no equipment required 
        "beta:donationPaymentUrl": "https://ourparks.org.uk/content/contribute-our-parks", // hard coded 
        "name": "Bootcamp", // classType
        "description": "A fitness bootcamp class that mixes traditional calisthenic and body weight exercises, with interval and strength training.\r\n\r\nMeeting Point: Tennis Courts by the Car Park", // strip_tags(description)
        "beta:formattedDescription": "<p>A fitness bootcamp class that mixes traditional calisthenic and body weight exercises, with interval and strength training.</p>\r\n\r\n<p><strong>Meeting Point: </strong>Tennis Courts by the Car Park&nbsp;</p>", // description
        "meetingPoint": "Basketball Courts", // meetingPoint (this property exactly matches OA already)
        "genderRestriction": "https://openactive.io/NoRestriction", // Hard coded (check with Born?)
        "ageRange": {
          "@type": "QuantitativeValue",
          "minValue": 16 // Hard coded (check with Born?)
        },
        "level": [
          "MODERATE" // exertion
        ],
        "maximumAttendeeCapacity": 30, // maxAttendees (use for in-person sessions)
        "maximumVirtualAttendeeCapacity": 30, // maxAttendees (use for online sessions)
        "url": "https://ourparks.org.uk/borough/ridgeway-park/bootcamp-96", // sessionUrl
        "leader": [
          {
            "@type": "Person",
            "identifier": "channon_nicole", // classCoachUsername
            "givenName": "Channon", // classCoachFirstName,
            "image": [
              {
                "@type": "ImageObject",
                "url": "https://ourparks.org.uk/sites/default/files/pictures/picture-254-1396133906.jpg", //classCoachImageURL
                "thumbnail": [
                  {
                    "@type": "ImageObject",
                    "url": "https://ourparks.org.uk/sites/default/files/styles/thumbnail/public/pictures/picture-254-1396133906.jpg" //classCoachImageThumbnailURL
                  },
                  {
                    "@type": "ImageObject",
                    "url": "https://ourparks.org.uk/sites/default/files/styles/50x50/public/pictures/picture-254-1396133906.jpg", //classCoachImage50x50URL
                    "width": 50,
                    "height": 50
                  }
                ]
              }
            ]
          }
        ],
        "image": [
          {
            "@type": "ImageObject",
            "url": "https://ourparks.org.uk/sites/default/files/classes/boot-camp_0.png" // eventLogo
          }
        ],
        "beta:video": [
          {
            "@type": "ImageObject",
            "url": "https://www.youtube.com/example" // video
          }
        ],
        "beta:affiliatedLocation": { //For virtual sessions, this property is called "beta:affiliatedLocation", otherwise it is called "location". The contents is the same in either case, and comes from park.
          "@type": "Place",
          "name": "Ridgeway Park", //park.title
          "description": "FREE exercise in Ridgeway Park, Waltham Forest London. Fitness classes include: Yoga, Pilates Bootcamp, Running, Abs workout, Cardio Tennis, Zumba, Circuits, Dance Fit and Buggy Exercise.\nPostcode: E4 6XU", //strip_tags(park.description)
          "beta:formattedDescription": "<p>FREE exercise in Ridgeway Park, Waltham Forest London. Fitness classes include: Yoga, Pilates Bootcamp, Running, Abs workout, Cardio Tennis, Zumba, Circuits, Dance Fit and Buggy Exercise. &nbsp;</p>\r\n\r\n<p><strong>Postcode:</strong>&nbsp;E4 6XU</p>\r\n\r\n<p>&nbsp;</p>\r\n", //park.description
          "identifier": 47, //park.id (as integer)
          "address": {
            "@type": "PostalAddress",
            "streetAddress": "The Ridgeway", //park.address1
            "addressLocality": "", //park.address2 (note null and empty strings will not be serialised by the library, which is the correct behaviour)
            "addressRegion": "Chingford", //park.city
            "postalCode": "E4 6XU", //park.postcode
            "addressCountry": "GB" //park.country
          },
          "geo": { // Do you have these in your database? The geo coordinates for the Park?
            "@type": "GeoCoordinates",
            "latitude": 54.543964,
            "longitude": -1.20978500000001
          },
          "image": [
            {
              "@type": "ImageObject",
              "url": "https://ourparks.org.uk/sites/default/files/parks/Ridgeway%20Park%20crop_0.jpg" //park.parkLogo
            }
          ]
        },
        "programme": { // content comes from borough
          "@type": "Brand",
          "name": "Our Parks Waltham Forest", // "Our Parks " + borough.title
          "url": "https://ourparks.org.uk/borough/waltham-forest", // borough url
          "identifier": 46, //borough.id (as integer)
          "description": "FREE exercise classes across Waltham Forest London Parks including: Yoga, Abs Workout, Circuit, Bootcamps, Run Classes. All outdoor fitness sessions are for women and men.\r\n", //strip_tags(borough.introText)
          "beta:formattedDescription": "<p>FREE exercise classes across Waltham Forest London Parks including: Yoga, Abs Workout, Circuit, Bootcamps, Run Classes. All outdoor fitness sessions are for women and men.</p>\r\n", //borough.introText
          "logo": {
            "@type": "ImageObject",
            "url": "https://ourparks.org.uk/sites/default/files/parks/Ridgeway%20Park%20crop_0.jpg" //borough.boroughLogo
          },
          "beta:video": [
            {
              "@type": "VideoObject",
              "name": "Some title", //borough.boroughVideoTitle
              "url": "https://www.youtube.com/watch?v=U4BhOHL8Aqg&t=29s" //borough.boroughVideo
            }
          ],
          "sameAs": [
            "https://twitter.com/edinjoy" // "https://twitter.com/" + borough.boroughTwitterAccount
          ]
        },

        "organizer": { // content is hard coded for all of Our Parks
          "@type": "Organization",
          "@id": "https://ourparks.org.uk/", // hard coded
          "name": "Our Parks", // hard coded
          "url": "https://www.ourparks.org.uk/", // hard coded
          "logo": {
            "@type": "ImageObject",
            "url": "https://www.ourparks.org.uk/sites/all/themes/commons/commons_origins/images/logo.png" // hard coded
          },
          "email": "getfitnow@ourparks.org.uk", // hard coded
          "telephone": "0800 111 4464", // hard coded
          "sameAs": [
            "http://instagram.com/OurParksUk", // hard coded
            "http://facebook.com/ourparks", // hard coded
            "https://www.youtube.com/channel/UCKTBvoYglo-As3GBURHI8fA", // hard coded
            "https://twitter.com/ourparksuk" // hard coded
          ]
        },

        "activity": [
          {
            "@type": "Concept",
            "@id": "https://openactive.io/activity-list#5e78bcbe-36db-425a-9064-bf96d09cc351", // phase 2: activity list ID, from https://openactive.io/activity-list/activity-list.jsonld
            "prefLabel": "Bootcamp", // classType
            "inScheme": "https://openactive.io/activity-list" // phase 2: hard coded
          }
        ],

        "startDate": "2014-03-22T11:00:00+01:00", // classDate with classTime (the library should add the local timezone automatically)
        "duration": "PT30M", // do you have the class duration stored somewhere?
        "endDate": "2014-03-22T12:00:00+01:00", // do you have the class end date/time stored somewhere, or could you calculate from duration?
        "eventStatus": "https://schema.org/EventScheduled", // if classStatus == "active"
        // "eventStatus": "https://schema.org/EventCancelled", // if classStatus != "active"
        "offers": [
          {
            "@type": "Offer",
            "price": 0,
            "priceCurrency": "GBP",
            "eligibleCustomerType": "https://openactive.io/ns-beta#Member", // hard coded for premium classes only
            "url": "https://ourparks.org.uk/memberships" // hard coded for premium classes only
          }
        ]
      }
    }
  ],
  "license": "https://creativecommons.org/licenses/by/4.0/"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
example Example JSON from an implementation
Projects
None yet
Development

No branches or pull requests

4 participants