|
9 | 9 | from feeds.impl.error_handling import raise_http_error, raise_http_validation_error, convert_exception |
10 | 10 | from shared.db_models.feed_impl import FeedImpl |
11 | 11 | from shared.db_models.gbfs_feed_impl import GbfsFeedImpl |
| 12 | +from shared.db_models.gtfs_feed_availability_check_impl import GtfsFeedAvailabilityCheckImpl |
12 | 13 | from shared.db_models.gtfs_feed_impl import GtfsFeedImpl |
13 | 14 | from shared.db_models.gtfs_rt_feed_impl import GtfsRTFeedImpl |
14 | 15 | from feeds_gen.apis.feeds_api_base import BaseFeedsApi |
15 | 16 | from feeds_gen.models.feed import Feed |
16 | 17 | from feeds_gen.models.gbfs_feed import GbfsFeed |
17 | 18 | from feeds_gen.models.gtfs_dataset import GtfsDataset |
18 | 19 | from feeds_gen.models.gtfs_feed import GtfsFeed |
| 20 | +from feeds_gen.models.gtfs_feed_availability_response import GtfsFeedAvailabilityResponse |
19 | 21 | from feeds_gen.models.gtfs_rt_feed import GtfsRTFeed |
20 | 22 | from middleware.request_context import is_user_email_restricted |
21 | 23 | from shared.common.db_utils import ( |
|
26 | 28 | get_gbfs_feeds_query, |
27 | 29 | ) |
28 | 30 | from shared.common.error_handling import ( |
| 31 | + availability_from_after_to, |
29 | 32 | invalid_date_message, |
30 | 33 | feed_not_found, |
31 | 34 | gtfs_feed_not_found, |
|
38 | 41 | Feed as FeedOrm, |
39 | 42 | Gtfsdataset, |
40 | 43 | Gtfsfeed, |
| 44 | + GtfsFeedAvailabilityCheck, |
41 | 45 | Gtfsrealtimefeed, |
42 | 46 | ) |
43 | 47 | from shared.feed_filters.feed_filter import FeedFilter |
@@ -308,6 +312,53 @@ def get_gtfs_feed_gtfs_rt_feeds(self, id: str, db_session: Session) -> List[Gtfs |
308 | 312 | else: |
309 | 313 | raise_http_error(404, gtfs_feed_not_found.format(id)) |
310 | 314 |
|
| 315 | + @with_db_session |
| 316 | + def get_gtfs_feed_availability( |
| 317 | + self, |
| 318 | + id: str, |
| 319 | + _from: str, |
| 320 | + to: str, |
| 321 | + limit: int, |
| 322 | + offset: int, |
| 323 | + sort: str, |
| 324 | + db_session: Session, |
| 325 | + ) -> GtfsFeedAvailabilityResponse: |
| 326 | + """Returns historical availability checks for a GTFS feed.""" |
| 327 | + if _from and not valid_iso_date(_from): |
| 328 | + raise_http_validation_error(invalid_date_message.format("from")) |
| 329 | + if to and not valid_iso_date(to): |
| 330 | + raise_http_validation_error(invalid_date_message.format("to")) |
| 331 | + |
| 332 | + from_dt = datetime.fromisoformat(_from.replace("Z", "+00:00")) if _from else None |
| 333 | + to_dt = datetime.fromisoformat(to.replace("Z", "+00:00")) if to else None |
| 334 | + |
| 335 | + if from_dt and to_dt and from_dt > to_dt: |
| 336 | + raise_http_validation_error(availability_from_after_to) |
| 337 | + |
| 338 | + feed = self._get_gtfs_feed(id, db_session, include_options_for_joinedload=False) |
| 339 | + if not feed: |
| 340 | + raise_http_error(404, gtfs_feed_not_found.format(id)) |
| 341 | + |
| 342 | + query = db_session.query(GtfsFeedAvailabilityCheck).filter(GtfsFeedAvailabilityCheck.feed_id == feed.id) |
| 343 | + if from_dt: |
| 344 | + query = query.filter(GtfsFeedAvailabilityCheck.checked_at >= from_dt) |
| 345 | + if to_dt: |
| 346 | + query = query.filter(GtfsFeedAvailabilityCheck.checked_at <= to_dt) |
| 347 | + |
| 348 | + total = query.count() |
| 349 | + order = ( |
| 350 | + GtfsFeedAvailabilityCheck.checked_at.asc() if sort == "asc" else GtfsFeedAvailabilityCheck.checked_at.desc() |
| 351 | + ) |
| 352 | + checks = query.order_by(order).offset(offset).limit(limit).all() |
| 353 | + |
| 354 | + return GtfsFeedAvailabilityResponse( |
| 355 | + feed_id=id, |
| 356 | + total=total, |
| 357 | + offset=offset, |
| 358 | + limit=limit, |
| 359 | + checks=[GtfsFeedAvailabilityCheckImpl.from_orm(c) for c in checks], |
| 360 | + ) |
| 361 | + |
311 | 362 | @with_db_session |
312 | 363 | def get_gbfs_feed( |
313 | 364 | self, |
|
0 commit comments