Skip to content

Commit

Permalink
(PC-32262)[API] feat: remove collective offer beginningDatetime in pu…
Browse files Browse the repository at this point in the history
…blic api
  • Loading branch information
jcicurel-pass committed Jan 14, 2025
1 parent 762e886 commit f3c2cc0
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 204 deletions.
11 changes: 11 additions & 0 deletions api/documentation/src/pages/change-logs.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ title: Pass Culture API change logs
**You can find a migration tutorial [here](/docs/tutorials/migrate-to-the-new-api).**
:::

## January 2025
- The `beginningDatetime` has been removed from the following endpoints:
- Removed from the return value:
- [**Get Collective Offer endpoint**](/rest-api#tag/Collective-Offers/operation/GetCollectiveOfferPublic)
- [**Get Collective Offers endpoint**](/rest-api#tag/Collective-Offers/operation/GetCollectiveOffersPublic)
- Removed from the input body and the return value:
- [**Create Collective Offer endpoint**](/rest-api#tag/Collective-Offers/operation/PostCollectiveOfferPublic)
- [**Update Collective Offer endpoint**](/rest-api#tag/Collective-Offers/operation/PatchCollectiveOfferPublic)
Please use the `startDatetime` and `endDatetime` fields instead.
The `startDatetime` field will be required when creating a collective offer and its value will be copied to `endDatetime` if `endDatetime` is not provided.

## December 2024

### Individual offers endpoints
Expand Down
54 changes: 12 additions & 42 deletions api/documentation/static/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1811,12 +1811,6 @@
},
"CollectiveOffersResponseModel": {
"properties": {
"beginningDatetime": {
"description": "Collective offer beginning datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"example": "2025-07-24T14:00:00+02:00",
"title": "Beginningdatetime",
"type": "string"
},
"bookings": {
"items": {
"$ref": "#/components/schemas/CollectiveBookingResponseModel"
Expand All @@ -1825,7 +1819,7 @@
"type": "array"
},
"endDatetime": {
"description": "Collective offer end datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"description": "Collective offer end datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime). When creating a collective offer, the value of `startDatetime` will be copied to `endDatetime` if `endDatetime` is not provided.",
"example": "2025-07-24T14:00:00+02:00",
"title": "Enddatetime",
"type": "string"
Expand All @@ -1837,7 +1831,7 @@
"type": "integer"
},
"startDatetime": {
"description": "Collective offer start datetime. Replaces beginning dateime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"description": "Collective offer start datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime). When creating a collective offer, the value of `startDatetime` will be copied to `endDatetime` if `endDatetime` is not provided.",
"example": "2025-07-24T14:00:00+02:00",
"title": "Startdatetime",
"type": "string"
Expand All @@ -1857,7 +1851,6 @@
},
"required": [
"id",
"beginningDatetime",
"startDatetime",
"endDatetime",
"status",
Expand Down Expand Up @@ -4138,12 +4131,6 @@
"title": "Audiodisabilitycompliant",
"type": "boolean"
},
"beginningDatetime": {
"description": "Collective offer beginning datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"example": "2025-07-24T14:00:00+02:00",
"title": "Beginningdatetime",
"type": "string"
},
"bookingEmails": {
"description": "Recipient emails for notifications about bookings, cancellations, etc.",
"example": [
Expand All @@ -4158,7 +4145,7 @@
"type": "array"
},
"bookingLimitDatetime": {
"description": "Booking limit datetime. It must be anterior to the `beginning_datetime`. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"description": "Booking limit datetime. It must be anterior to the `start_datetime`. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"example": "2025-07-24T14:00:00+02:00",
"title": "Bookinglimitdatetime",
"type": "string"
Expand Down Expand Up @@ -4235,7 +4222,7 @@
"type": "string"
},
"endDatetime": {
"description": "Collective offer end datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"description": "Collective offer end datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime). When creating a collective offer, the value of `startDatetime` will be copied to `endDatetime` if `endDatetime` is not provided.",
"example": "2025-07-24T14:00:00+02:00",
"title": "Enddatetime",
"type": "string"
Expand Down Expand Up @@ -4334,7 +4321,7 @@
"$ref": "#/components/schemas/OfferVenueModel"
},
"startDatetime": {
"description": "Collective offer start datetime. Replaces beginning dateime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"description": "Collective offer start datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime). When creating a collective offer, the value of `startDatetime` will be copied to `endDatetime` if `endDatetime` is not provided.",
"example": "2025-07-24T14:00:00+02:00",
"title": "Startdatetime",
"type": "string"
Expand Down Expand Up @@ -4385,7 +4372,6 @@
"hasBookingLimitDatetimesPassed",
"isSoldOut",
"venueId",
"beginningDatetime",
"startDatetime",
"endDatetime",
"bookingLimitDatetime",
Expand Down Expand Up @@ -5731,14 +5717,6 @@
"title": "Audiodisabilitycompliant",
"type": "boolean"
},
"beginningDatetime": {
"description": "Collective offer beginning datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"example": "2025-07-24T14:00:00+02:00",
"format": "date-time",
"nullable": true,
"title": "Beginningdatetime",
"type": "string"
},
"bookingEmails": {
"description": "Recipient emails for notifications about bookings, cancellations, etc.",
"example": [
Expand All @@ -5753,7 +5731,7 @@
"type": "array"
},
"bookingLimitDatetime": {
"description": "Booking limit datetime. It must be anterior to the `beginning_datetime`. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"description": "Booking limit datetime. It must be anterior to the `start_datetime`. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"example": "2025-07-24T14:00:00+02:00",
"format": "date-time",
"nullable": true,
Expand Down Expand Up @@ -5823,7 +5801,7 @@
"type": "string"
},
"endDatetime": {
"description": "Collective offer end datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"description": "Collective offer end datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime). When creating a collective offer, the value of `startDatetime` will be copied to `endDatetime` if `endDatetime` is not provided.",
"example": "2025-07-24T14:00:00+02:00",
"format": "date-time",
"nullable": true,
Expand Down Expand Up @@ -5915,7 +5893,7 @@
"title": "OfferVenueModel"
},
"startDatetime": {
"description": "Collective offer start datetime. Replaces beginning dateime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"description": "Collective offer start datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime). When creating a collective offer, the value of `startDatetime` will be copied to `endDatetime` if `endDatetime` is not provided.",
"example": "2025-07-24T14:00:00+02:00",
"format": "date-time",
"nullable": true,
Expand Down Expand Up @@ -5995,13 +5973,6 @@
"title": "Audiodisabilitycompliant",
"type": "boolean"
},
"beginningDatetime": {
"description": "Collective offer beginning datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"example": "2025-07-24T14:00:00+02:00",
"format": "date-time",
"title": "Beginningdatetime",
"type": "string"
},
"bookingEmails": {
"description": "Recipient emails for notifications about bookings, cancellations, etc.",
"example": [
Expand All @@ -6015,7 +5986,7 @@
"type": "array"
},
"bookingLimitDatetime": {
"description": "Booking limit datetime. It must be anterior to the `beginning_datetime`. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"description": "Booking limit datetime. It must be anterior to the `start_datetime`. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"example": "2025-07-24T14:00:00+02:00",
"format": "date-time",
"title": "Bookinglimitdatetime",
Expand Down Expand Up @@ -6080,7 +6051,7 @@
"type": "string"
},
"endDatetime": {
"description": "Collective offer end datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"description": "Collective offer end datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime). When creating a collective offer, the value of `startDatetime` will be copied to `endDatetime` if `endDatetime` is not provided.",
"example": "2025-07-24T14:00:00+02:00",
"format": "date-time",
"nullable": true,
Expand Down Expand Up @@ -6152,10 +6123,9 @@
"$ref": "#/components/schemas/OfferVenueModel"
},
"startDatetime": {
"description": "Collective offer start datetime. Replaces beginning dateime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime).",
"description": "Collective offer start datetime. It cannot be a date in the past. The expected format is **[ISO 8601](https://fr.wikipedia.org/wiki/ISO_8601)** (standard format for timezone aware datetime). When creating a collective offer, the value of `startDatetime` will be copied to `endDatetime` if `endDatetime` is not provided.",
"example": "2025-07-24T14:00:00+02:00",
"format": "date-time",
"nullable": true,
"title": "Startdatetime",
"type": "string"
},
Expand Down Expand Up @@ -6204,7 +6174,7 @@
"students",
"offerVenue",
"isActive",
"beginningDatetime",
"startDatetime",
"bookingLimitDatetime",
"totalPrice",
"numberOfTickets"
Expand Down
16 changes: 7 additions & 9 deletions api/src/pcapi/core/educational/api/offer.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,9 +481,9 @@ def create_collective_offer_public(

collective_stock = educational_models.CollectiveStock(
collectiveOffer=collective_offer,
beginningDatetime=body.beginning_datetime,
startDatetime=body.start_datetime or body.beginning_datetime,
endDatetime=body.end_datetime or body.beginning_datetime,
beginningDatetime=body.start_datetime, # TODO: this field is still required, the column will be removed later
startDatetime=body.start_datetime,
endDatetime=body.end_datetime or body.start_datetime,
bookingLimitDatetime=body.booking_limit_datetime,
price=body.total_price,
numberOfTickets=body.number_of_tickets,
Expand Down Expand Up @@ -570,7 +570,7 @@ def edit_collective_offer_public(
offer.offerVenue["otherAddress"] = value.get("otherAddress") or ""
elif key == "bookingLimitDatetime" and value is None:
offer.collectiveStock.bookingLimitDatetime = new_values.get(
"beginningDatetime", offer.collectiveStock.beginningDatetime
"startDatetime", offer.collectiveStock.startDatetime
)
elif key in stock_fields:
setattr(offer.collectiveStock, key, value)
Expand All @@ -582,15 +582,13 @@ def edit_collective_offer_public(
api_shared.update_collective_stock_booking(
stock=offer.collectiveStock,
current_booking=collective_stock_unique_booking,
beginning_datetime_has_changed="beginningDatetime" in new_values,
datetime_has_changed="startDatetime" in new_values,
datetime_column="startDatetime",
)

db.session.commit()

notify_educational_redactor_on_collective_offer_or_stock_edit(
offer.id,
updated_fields,
)
notify_educational_redactor_on_collective_offer_or_stock_edit(offer.id, updated_fields)
return offer


Expand Down
21 changes: 12 additions & 9 deletions api/src/pcapi/core/educational/api/shared.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import datetime
import typing

from pcapi.core.educational import exceptions as educational_exceptions
from pcapi.core.educational import models as educational_models
Expand All @@ -10,7 +11,8 @@
def update_collective_stock_booking(
stock: educational_models.CollectiveStock,
current_booking: educational_models.CollectiveBooking | None,
beginning_datetime_has_changed: bool,
datetime_has_changed: bool,
datetime_column: typing.Literal["startDatetime"] | typing.Literal["beginningDatetime"],
) -> None:
"""When a collective stock is updated, we also update some fields of its related booking"""

Expand All @@ -32,33 +34,34 @@ def update_collective_stock_booking(
if booking_to_update:
booking_to_update.confirmationLimitDate = booking_limit_value

if beginning_datetime_has_changed:
_update_collective_booking_cancellation_limit_date(booking_to_update, stock.beginningDatetime)
_update_collective_booking_educational_year_id(booking_to_update, stock.beginningDatetime)
if datetime_has_changed:
start = getattr(stock, datetime_column)
_update_collective_booking_cancellation_limit_date(booking_to_update, start)
_update_collective_booking_educational_year_id(booking_to_update, start)


def _update_collective_booking_educational_year_id(
booking: educational_models.CollectiveBooking,
new_beginning_datetime: datetime.datetime,
new_start_datetime: datetime.datetime,
) -> None:
educational_year = educational_repository.find_educational_year_by_date(new_beginning_datetime)
educational_year = educational_repository.find_educational_year_by_date(new_start_datetime)
if educational_year is None:
raise educational_exceptions.EducationalYearNotFound()

booking.educationalYear = educational_year


def _update_collective_booking_cancellation_limit_date(
booking: educational_models.CollectiveBooking, new_beginning_datetime: datetime.datetime
booking: educational_models.CollectiveBooking, new_start_datetime: datetime.datetime
) -> None:
# if the input date has a timezone (resp. does not have one), we need to compare it with an aware datetime (resp. a naive datetime)
now = (
datetime.datetime.utcnow()
if new_beginning_datetime.tzinfo is None
if new_start_datetime.tzinfo is None
else datetime.datetime.now(datetime.timezone.utc) # pylint: disable=datetime-now
)
booking.cancellationLimitDate = educational_utils.compute_educational_booking_cancellation_limit_date(
new_beginning_datetime, now
new_start_datetime, now
)


Expand Down
3 changes: 2 additions & 1 deletion api/src/pcapi/core/educational/api/stock.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,8 @@ def edit_collective_stock(
api_shared.update_collective_stock_booking(
stock=stock,
current_booking=current_booking,
beginning_datetime_has_changed="beginningDatetime" in stock_data,
datetime_has_changed="beginningDatetime" in stock_data,
datetime_column="beginningDatetime",
)

db.session.flush()
Expand Down
3 changes: 2 additions & 1 deletion api/src/pcapi/routes/public/collective/endpoints/offers.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ def patch_collective_offer_public(
"students",
"offerVenue",
"interventionArea",
"beginningDatetime",
"startDatetime",
"endDatetime",
"totalPrice",
"numberOfTickets",
"audioDisabilityCompliant",
Expand Down
Loading

0 comments on commit f3c2cc0

Please sign in to comment.