Files
040-personal-flight-club/docs/milestones/mil-002-flight-data-and-indirect-search.md
2026-10-24 23:35:34 +08:00

71 lines
3.1 KiB
Markdown

# MIL-002 Flight data and indirect search
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-002 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-24 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c5a6ed5] |
---
## Purpose
Decide whether the flight search handles destinations without direct flights (assignment Step 3).
## Deliverable
`FlightData` with a `stops` attribute; `FlightSearch.check_flights(origin_city_code, destination_city_code, from_time, to_time, is_direct=True)` using the SerpAPI `stops` parameter (and the mock provider's equivalent); `main.py` falling back to an indirect search with the assignment's console messages.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | `FlightData.__init__()` takes `stops` and stores it; stops are computed as `len(flight["flights"]) - 1` | Unit tests pass | Missing or wrong |
| 2 | `check_flights(..., is_direct=True)` sends the nonstop filter, and `is_direct=False` sends the filter that allows 1 or 2 stops | Unit test on the request parameters | Wrong parameters |
| 3 | `main` prints "Getting direct flights for [city]..." and, when the price is "N/A", "No direct flight to [city]. Looking for indirect flights..." and searches with `is_direct=False` | Unit test with fakes | No fallback |
| 4 | No test uses the network or the real `.env` | Verified | Violated |
## Dependencies
| Depends on | Reason |
| --- | --- |
| MIL-001 | Builds on the previous phase |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 1 | [BC-001] Objectives |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 |
## Target Date
2026-10-29 — within the two-week plan window of the Project Plan.
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | FlightData stops | Add `stops` to `FlightData.__init__()` and to the "N/A" result. Compute `nr_stops = len(flight["flights"]) - 1` when parsing a response. | No | |
| 2 | check_flights with is_direct | Add the `is_direct=True` parameter. Direct: SerpAPI `stops=1` (nonstop only). Indirect: the SerpAPI value for up to 1 or 2 stops; the mock provider filters by number of stops. Pass the stops to `FlightData`. Keep the response cache. | No | |
| 3 | Indirect fallback in main | For each destination, search direct first; if `cheapest_flight.price == "N/A"`, print the fallback message and search again with `is_direct=False`. Keep the Day 39 price comparison, sheet update and WhatsApp message. | No | |
| 4 | Tests for stops and fallback | Unit tests for parsing the stops, the request parameters of both searches and the fallback logic, using fakes only. | No | |
---
[BC-001]: ../business-case.md
[c5a6ed5]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/040-personal-flight-club/commit/c5a6ed5985f76d8836f763acc5638053a39157f2