culturecreates / artsdata-data-model

Overview of how data is modelled in Artsdata.ca.
https://culturecreates.github.io/artsdata-data-model/
Creative Commons Zero v1.0 Universal
12 stars 6 forks source link

Offer: help needed to model offers #80

Open saumier opened 10 months ago

saumier commented 10 months ago

How to model offers in RDF such that the most common use cases for events in the cultural sector are well expressed and can drive a website page with the needed information displayed and buttons with links to buy tickets or register.

The following cases occur on cultural event websites such as https://signelaval.com/fr/evenements

  1. free - event is free
  2. paid - event requires a payment
  3. free with registration - event is free but participants are required to register for the event in advance
  4. paid with registration - event requires a payment and participants are required to register for the event in advance

Issues to explore

Proposed solution

Create a controlled vocabulary of types of Offer:

Is there a better and more standard solution? How to other ontologies express these needs?

Example forms that need to be expressed in RDF

These forms have 3 types of tickets. The Paid ticket that requires registration is not illustrated, but is a real need.

Screenshot 2023-09-21 at 3 57 06 PM

Paid event

Proposed RDF (turtle) with Offers at the same level as AggregateOffer.

offers 
     [
         a AggregateOffer  ;
         additionalType ado:OfferIsPaid ;
         url "Entrez l'adresse web URL" ;
         name "Ajouter des informations supplémentaires sur la billeterie"@fr 
     ] , 
    [ 
        a Offer  ;
        price "25.0" ;
        name "Enfants"@fr 
    ] ,
   [ 
        a Offer  ;
        price "55.0" ;
        name "Adultes"@fr 
    ] .
Screenshot 2023-09-21 at 3 29 18 PM

Free event

Proposed RDF (turtle)

offers [ 
     a AggregateOffer  ;
     additionalType adr:OfferIsFree ;
     name "Ajouter des informations supplémentaires sur la billeterie"@fr ]
Screenshot 2023-09-21 at 3 28 55 PM

Free event with a link to register

Proposed RDF (turtle) with url for registration.

offers [ 
     a AggregateOffer  ;
     additionalType  adr:OfferIsFreeWithRegistration ;
     url "Entrez l'adresse web URL" ;
     schema:name "Ajouter des informations supplémentaires sur la billeterie"@fr ] .
Screenshot 2023-09-21 at 3 29 36 PM
saumier commented 9 months ago

@fjjulien Please let me know if you have any questions on this documentation. Thx.

fjjulien commented 9 months ago

@fjjulien Please let me know if you have any questions on this documentation. Thx.

This is much clearer, now. The only case I can't mentally represent is the fourth one: paid with registration. A payment checkout process involves de facto the same kinds of questions as a registration process. What kinds of events in the performing arts sector would need that? A conference in which a single payment can be made for multiple delegate registrations?

saumier commented 9 months ago

The "paid with registration" use case is coming from Isabelle at Tout Culture. I think it has to do with workshops like dance. The webpage describing the master class needs to have people register only, then later they will pay.

@troughc Can you provide some more background as to why Isabelle needs this use case? Thx.

fjjulien commented 9 months ago

Thanks that is useful.

I'm having a heard time mentally representing a "paid with registration" event in the context of the performing arts. A payment checkout process involves the same kind of questions as a registration process. Why require the user to do the same kind of process twice?

troughc commented 9 months ago

@fjjulien the problem is that there are courses (i.e. an art class like painting) and workshops in Tout Culture. These require Registration AND payment.

With the current model, we ONLY have free with registration (so all events that require registration are FREE).

We need to be able to have a PAID registration option for classes/workshops/conference events that a person might want to attend.

I had suggested that we remove the precondition FREE with registration. However, Maude needs FREE registration for her website to accurately display information. So we need both FREE and PAID options.

Example: an art course that requires registration and has a price associated: https://www.visualartscentre.ca/register/?action=course_detail&course_id=7306

Anicetondo commented 9 months ago

**Quelques suggestions sur un évènement et les éventuels détails sur l’offre de spectacle:

Modélisez l’événement culturel lui-même en tant que ressource principale. Cette ressource principale peut être liée à toutes les autres informations associées à l’événement, y compris les offres de billets.**

**Quelques modèles d’un évènement spécifique:

(Ceci existe déjà dans votre représentation)**

:Event1 a schema:Event ; schema:name "Nom de l'événement" ; schema:description "Description de l'événement" ; schema:startDate "2023-10-15T19:00:00"^^xsd:dateTime ; schema:endDate "2023-10-15T21:00:00"^^xsd:dateTime .

Concernant les Offres de billets : Modélisez les différentes offres pour l’événement en se servant du vocabulaire schema.org. Pour chaque offre , spécifiez si l’événement est gratuit, payant, nécessite une inscription, ou les combinaisons de ces options :

Exemple spécifique( quelques propriétés peuvent être retirées si elles ne sont jugées utiles)

**:Event1 schema:offers [

a schema:Offer ;
schema:name "Billet standard" ;
schema:description "Billet d'entrée standard" ;
schema:price 20.00 ;
schema:priceCurrency "CAD" ;
schema:availability schema:InStock ;
schema:validFrom "2023-09-23"^^xsd:date ;
schema:validThrough "2023-10-15"^^xsd:date ;
schema:eligibleCustomerType schema:Public ;
schema:availabilityStarts "2023-09-23T10:00:00"^^xsd:dateTime ;
schema:availabilityEnds "2023-10-15T18:00:00"^^xsd:dateTime ;
schema:requiresSubscription false ;

] .**

Conditions d’inscription : Pour les événements avec inscription, vous pouvez utiliser une propriété personnalisée pour spécifier les détails de l’inscription. Par exemple :

:Event1 ex:registrationRequirement [

ex:requiresRegistration true ;
ex:registrationURL "URL de la page d'inscription" ;

] .

Concernant l’option l’offre est gratuite ou payante : il est possible de structurer cela avec la propriété schema:price pour indiquer le prix du billet. et la condition serait donc ''''Si le prix est de zéro, l’événement est gratuit'''''.

Liens d’achat de billets : Vous pouvez ajouter des propriétés personnalisées pour les liens d’achat de billets. Par exemple :

:Event1 ex:buyTicketsURL « URL d’achat de billets » .

Anicetondo commented 9 months ago

Je pense que cette façon pourrait aider pour modéliser les offres de spectacles par rapport à l’idée qui est demandée. Je pense que cette façon pourrait aider pour modéliser les offres de spectacles par rapport à l’idée qui est demandée

Anicetondo commented 9 months ago

Mais si toutes les offres nécessitent une inscription, la il n'y aurait plus de condition à ce niveau :Event1 ex:registrationRequirement [

ex:requiresRegistration true ; ex:registrationURL "URL de la page d'inscription" ; ] .

le formulaire d'inscription sera alors présenté pour chaque offre

L'autre idée serait un peu similaire à la solution énoncée plus haut(solution de saumier)

mais à la différence qu'on peut avoir une propriété 'nature de l'offre' de telle sorte que pour une offre donnée cette propriété puisse prendre une des valeurs: 'Free' ou 'Paid' en ajoutant une restriction à la propriété.

saumier commented 9 months ago

@Anicetondo Merci pour les suggestions.

I am trying to not add additional properties like ex:registrationRequirement and ex:buyTicketsURL directly to Events but rather I am trying to group them in schema:offers. Is there something you can propose that uses properties within schema:Offer?

Anicetondo commented 9 months ago

@Anicetondo Merci pour les suggestions.

Cette façon de les regrouper dans schema : offers marche aussi c'est ce que je pourrait également proposer en modèle schéma sinon je vous ferai d'autres suggestions sous un format complémentaire au rdf

fjjulien commented 9 months ago

Comme Anicet, j'aurais tendance à décrire sémantiquement l'attribut "gratuit/payant" et la condition "requires registration" avec des propriétés distinctes. "Gratuit/payant" peut aisément être représenté avec schema:price, comme le suggère Anicet. "Requires registration" serait selon moi une condition (ou un pré-requis) qui doit être remplie par le client avant de pouvoir profiter de l'offre. Il pourrait y avoir d'autres conditions qui seraient décrites de la sorte, par exemple:

Si chacune des ces conditions devait être intégrée à un seul vocabulaire contrôlé, le nombre de valeurs deviendrait exponentielle (et le vocabulaire, inutile).

La solution qui m'apparaît donc la plus simple serait de créer une nouvelle propriété pour représenter les conditions associées à l'offre. Aucune des propriétés actuelles de Schema ne pourrait servir à représenter ce genre d'information. Il faudrait créer une propriété dans l'ontologie Artsdata. Éventuellement, cette propriété pourrait être proposée à Schema.

saumier commented 8 months ago

Reviewing the discussion thus far, I'd like to propose the following using schema:potentialAction. For more background: https://schema.org/docs/actions.html

Case 1: Free event

:event1 schema:offers [ 
     a schema:Offer  ;
     schema:price 0 
] .

Case 2: Free event with condition to register

:event2 schema:offers [ 
     a schema:Offer  ;
     schema:price 0 ;
    schema:potentialAction  [
         a schema:Action ;
        schema:additionalType  adr:RegistrationRequired ;
        schema:name "Please RSVP"@en ;
       schema:url "http://register.for.event2" ;
       ] .
] .

Case 3: Paid event with condition to register

:event3 schema:offers [ 
     a schema:Offer  ;
     schema:price 25.50 ;
    schema:potentialAction  [
         a schema:Action ;
        schema:additionalType  adr:RegistrationRequired ;
        schema:name "Signup for the workshop and pay later"@en ;
       schema:url "http://register.for.event 3" ;
       ] .
] .

@troughc @fjjulien @Anicetondo Let me know your thoughts. Thx.

There is also a discussion happening here with LaVitrine https://github.com/culturecreates/artsdata-planet-lavitrine/discussions/3

fjjulien commented 8 months ago

I believe the above strategy would be apt at representing a registration requirement (and any other requirement that involves any kind of interaction action on the part of the user) in a way that makes sense to us in Artsdata. But I'm not sure it is semantically sound. "potentialAction" is defined as, "Indicates a potential Action, which describes an idealised action in which this thing would play the 'object' role." In your model, the thing in subject position - that is, the offer to attend an event - is not the object of the action "RegistrationRequired" (which, strickly speaking, is not really an action, anyway).

Did you consider using the more specific @type ConsumeAction, instead of the generic Action type? It would add a semantic layer of meaning for human readers: it would designate the act of consuming/redeeming the offer (for example, attending the performance or participating in the workshop), which is the most obvious potential action that one could perform with regards to an offer.

The ConsumeAction also presents a formal advantage: it's the domain for the property actionAccessibilityRequirement. This property is defined as: "A set of requirements that must be fulfilled in order to perform an Action." This is precisely what you are attempting to describe: a condition or a requirement that must be met in order for the offer to be consumed.

The expected value for actionAccessibilityRequirement is ActionAccessSpecification, which is a highly adaptable concept, thanks to the category property, which can accept things and external URIs as value. You could use your own controlled vocabulary as a value and expand it as you see fit to include other common requirements such as "member required", "requires pre-approval", "must show ID with photo", etc. It could also be used to provide one off requirements as text, for example: "participants must be wearing an orange shirt".

This alternative modelling strategy requires another level of nesting, which would make the code longer to decrypt for a human reader. But if I was stumbling upon this kind of JSON-LD, I would fairly quickly understand what is being described and I would deem this modelling conceptually accurate.

saumier commented 8 months ago

@fjjulien Is this the correct representation of your suggestion ?

:event3 schema:offers [ 
    a schema:Offer  ;
    schema:price 25.50 ;
    schema:potentialAction  [
            a schema:ConsumeAction ;
            schema:actionAccessibilityRequirement [ 
                 a schema:ActionAccessSpecification ;
                 schema:category  adr:RegistrationRequired ;
                 schema:name "Signup for the workshop and pay later"@en ;
                 schema:url "http://register.for.event 3" 
         ] .
    ] .
] .

I am not sure if this is going to achieve our use case as it seems overly complex for both a human and a developer to write code to drive a website page with a "register" button.

If we look back at our goal...

How to model offers in RDF such that the most common use cases for events in the cultural sector are well expressed and can drive a website page with the needed information displayed and buttons with links to buy tickets or register.

... I think a simpler approach could be to keep Offer as it was and add a controlled vocabulary using additionalType. If this is semantically correct, then the simpler approach illustrated below would be easier for a developer to program the button to display "register" instead of "buy".

In my opinion we really are talking about a type of Offer that is slightly different than a regular offer. If another person where to stumble upon this additional type "RegistrationRequired" then a click on the URI would provide the documentation. This solution strays the least from the common usage of Offer and provides additional information about the Offer without changing the structure or adding too much complexity.

:event3 schema:offers [ 
    a schema:Offer  ;
    schema:price 25.50 ;
    schema:additionalType  adr:RegistrationRequired ;
    schema:name "Signup for the workshop and pay later"@en ;
    schema:url "http://register.for.event 3" 
] .
saumier commented 8 months ago

Here are some real scenarios from Signé Laval. The RDF model for Offer needs to be expressive enough to cover these cases.

@fjjulien @Anicetondo @troughc If we use an Offer with a price of 0 to indicate free, and an additionalType with an Artsdata controlled vocabulary to indicate "Registration Required", then I think we are covered for these scenarios.

Free event

https://signelaval.com/fr/evenements/651b0eae5cc75600644f691b/visite-commentee-de-lexposition-libby-hague Here "free" is displayed because the Offer price is 0, and there is no Offer url.

Screenshot 2023-11-01 at 8 42 13 AM

Free event requiring registration

https://signelaval.com/fr/evenements/6536be20a37f770066e6caa1/insectes-et-autres-arthropodes Here the "register" button (s'incrire a l'événement) is displayed because the offer has additionalType adr:RegistrationRequired. The button opens the Offer url.

Screenshot 2023-11-01 at 8 37 29 AM

Paid event single price

https://signelaval.com/fr/evenements/650bd2c65db0a100651e0baf/belmont Here the "buy" button (acheter des billets) is displayed because the offer has a non-zero price and the button opens the Offer url.

Screenshot 2023-11-01 at 8 42 59 AM

Paid event multiple prices

https://signelaval.com/fr/evenements/650297b9a59a070066be6d41/caroline-savoie-bruits-blancs Here the "buy" button is displayed because the offers have a non-zero price. Each offer has a price and a name (Adults, Children, etc.)

Here there are 2 choices: "AggregateOffer" that contains the buy url for all prices and general ticketing information ("Le prix inclut les taxes...") that applies to all offers. Or instead of using AggregateOffer, the url and description could be copied to each individual Offer. If the Offer url or description is different in each offer, then each Offer can have its own button and description, but this is unlikely for a listing site.

Screenshot 2023-11-01 at 8 45 14 AM

Paid event requiring registration

This scenario does not exist on Signé Laval.

fjjulien commented 8 months ago

@fjjulien Is this the correct representation of your suggestion ?

Yes, that is what I meant to describe. I believe this would be the "proper" way of representing this kind of information if we wanted to use the potentialAction property to follow Schema as closely as possible. This being said, I admit it is complicated. The only advantage of this modelling strategy is the use of the property actionAccessibilityRequirement: a developer could code an application to prevent a use from consuming an offer until the accessibility requirement has been verified and found to be true.

On the other hand, a developer could also applying conditional logic to an additionalType attribute-value pair, as you are proposing.

Upon considering all potential modelling strategies, I vote for the additionalType modelling approach. It is conceptually correct, it is much simpler than the other two, and it can easily be extended as needed.

fjjulien commented 8 months ago

If we use an Offer with a price of 0 to indicate free, and an additionalType with an Artsdata controlled vocabulary to indicate "Registration Required", then I think we are covered for these scenarios.

"Offer with a price of 0 to indicate free" -- This is definitely a better approach than creating an additional offer type for "Free Event" (because we could potentially run into conflicts where the additional type "FreeEvent" is used, and the price > 0).

fjjulien commented 8 months ago

... I think we are covered for these scenarios.

I believe we may need additional types for events with multiple prices.

In the example you provided, a membership/subscription is required for the two cheaper prices. This should be formally represented because I anticipate use cases for this kind of information. For example, it is common among cultural calendars to list the lowest available ticket price. If however a price requires that a condition be met (be it a membership or an age range), it shouldn't be listed as the lowest available ticket price. As a consumer visiting a city, I wouldn't want to see a show listed at $25 to then find out that the actual price for non-members is actually $35.

There's no need to create these additional types right away. It would be preferable to hold consultations with data consumers and with ticketing service providers, and attempt to define the types that would meet the most use cases.

fjjulien commented 8 months ago

Here's another use case that might require a controlled vocabulary term: offers with dynamic pricing.

As a data consumer managing a listings site, I would want to know that a given offer is subject to dynamic pricing. I may for example want to insert a disclaimer to the effect the this price is subject to change (and that the listings site may not responsible in case the price does change). I may also want to insert a timestamp indicating when the price was last validated.

fjjulien commented 7 months ago

Note: detailed schemas are now available in discussion https://github.com/culturecreates/artsdata-data-model/discussions/86.