|
| 1 | +--- |
| 2 | +ID: 'PRACTICA_ACTIVITY-BOOKINGS' |
| 3 | +Course: 'Copilot-CSharp' |
| 4 | +Archetype: 'CSharp-API' |
| 5 | +Author: 'Students' |
| 6 | +--- |
| 7 | +# PRD — Activity Bookings API |
| 8 | + |
| 9 | +## 1. Executive Summary |
| 10 | + |
| 11 | +REST API to manage bookings for tourist activities. The goal is for students to implement a basic CRUD (Create, Read, Update, Delete), persisting data to files (JSON, CSV, or XML). The solution does not require authentication, third-party services, or a database. |
| 12 | + |
| 13 | +### 1.1 Goals and Metrics |
| 14 | + |
| 15 | + * Build a working REST API with all endpoints functional locally. |
| 16 | + * Ensure the application can be run with the command `dotnet run`. |
| 17 | + * Implement unit and integration tests to validate API behavior. |
| 18 | + |
| 19 | +### 1.2 Audience |
| 20 | + |
| 21 | + * Students: to gain practical experience. |
| 22 | + * Instructors: to use as guidance and to assess learning outcomes. |
| 23 | + |
| 24 | +### 1.3 Technologies |
| 25 | + * Language: C# with .NET 9+. [ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/tutorials/min-web-api?view=aspnetcore-9.0&tabs=visual-studio) |
| 26 | + * Libraries: Minimal, preferably only `System.Net.Http` and `System.Text.Json`. |
| 27 | + * Tools: Visual Studio Code or Visual Studio with the .NET CLI |
| 28 | + * Deployment: Runnable service on localhost using the command `dotnet run`. |
| 29 | + |
| 30 | +## 2. Scope |
| 31 | + |
| 32 | + * Included: REST API with a basic CRUD backed by JSON, CSV, or XML files. |
| 33 | + * Excluded: Authentication, payments, notifications, databases. |
| 34 | + |
| 35 | +### 2.1 User Stories |
| 36 | + |
| 37 | + * As a user, I want to list all offered activities. |
| 38 | + * As a user, I want to view details of a specific activity. |
| 39 | + * As a user, I want to create a new booking for an activity. |
| 40 | + * As a user, I want to see all my bookings. |
| 41 | + * As a user, I want to cancel an existing booking. |
| 42 | + |
| 43 | +### 2.2 Functional Requirements |
| 44 | + |
| 45 | +1. RF-1: `GET /activities` - List all available activities. |
| 46 | +2. RF-2: `GET /activities/{id}` - Show details for a specific activity. |
| 47 | +3. RF-3: `POST /bookings` - Create a new booking. |
| 48 | +4. RF-4: `GET /bookings` - List all existing bookings. |
| 49 | +5. RF-5: `DELETE /bookings/{id}` - Cancel a booking. |
| 50 | + |
| 51 | +### 2.3 Additional Functional Requirements |
| 52 | + |
| 53 | +6. RF-6: `GET /activities/{id}/bookings` - List all bookings for a specific activity. |
| 54 | +7. RF-7: `PUT /bookings/{id}` - Update an existing booking. |
| 55 | +8. RF-8: `GET /activities?status={status}` - Filter activities by status (e.g. `available`, `finished`). |
| 56 | + |
| 57 | +### 2.4 Non-Functional Requirements |
| 58 | + |
| 59 | + * Simplicity: Prioritize clarity and simplicity in the implementation. |
| 60 | + * Design: The API should follow RESTful design with clear, consistent routes. |
| 61 | + * Performance: API responses should be fast, preferably under 1 second. |
| 62 | + * Persistence: Use JSON, CSV, or XML files for data storage. |
| 63 | + * Technologies: Use .NET 9+ and minimal NuGet packages. |
| 64 | + |
| 65 | +## 3. Data Model and Business Rules |
| 66 | + |
| 67 | +### 3.1 Data Schema |
| 68 | + |
| 69 | + * Activity: |
| 70 | + |
| 71 | + * `id` (int) |
| 72 | + * `name` (string) |
| 73 | + * `price` (float) |
| 74 | + * `date` (datetime) |
| 75 | + * `status` (string: `available`, `finished`, `cancelled`, `full`) |
| 76 | + * `capacity` (optional, int): maximum number of bookings. |
| 77 | + * `quorum` (optional, int): minimum number of bookings required for the activity to take place. |
| 78 | + |
| 79 | + * Booking: |
| 80 | + |
| 81 | + * `id` (int) |
| 82 | + * `activityId` (int) |
| 83 | + * `customerName` (string) |
| 84 | + * `bookingDate` (datetime) |
| 85 | + * `status` (string: `confirmed`, `cancelled`) |
| 86 | + |
| 87 | +### 3.2 Relationships |
| 88 | + |
| 89 | + * An Activity can have multiple Bookings. |
| 90 | + * A Booking belongs to a single Activity. |
| 91 | + |
| 92 | +### 3.3 Business Rules |
| 93 | + |
| 94 | + * Activities with status `finished` or `full` cannot be booked. |
| 95 | + * A booking cannot be cancelled if less than 48 hours remain before the activity starts. |
| 96 | + * When an activity reaches its `capacity`, its status must change to `full`. |
| 97 | + * If the `quorum` is not met 48 hours before the activity, the activity should be cancelled automatically and users notified (simulated with a log message). |
| 98 | + |
| 99 | +## 4. Acceptance Criteria and Risks |
| 100 | + |
| 101 | +### 4.1 Acceptance Criteria |
| 102 | + |
| 103 | + * Each endpoint returns human-readable JSON. |
| 104 | + * The API runs without errors. |
| 105 | + * Unit and integration tests pass. |
| 106 | + * I/O errors (file read/write) are handled properly. |
| 107 | + |
| 108 | +### 4.2 Risks |
| 109 | + |
| 110 | + * File handling errors (reading/writing) could corrupt data. |
| 111 | + |
| 112 | +## 5. Example Data (Seed Data) |
| 113 | + |
| 114 | +### 5.1 Activities |
| 115 | + |
| 116 | +```json |
| 117 | +[ |
| 118 | + {"id":1, "name":"City Tour", "price":50.0, "date":"2026-07-15T10:00:00", "status":"available", "capacity": 10}, |
| 119 | + {"id":2, "name":"Mountain Hike", "price":80.0, "date":"2026-07-20T08:00:00", "status":"available", "quorum": 5}, |
| 120 | + {"id":3, "name":"Museum Visit", "price":30.0, "date":"2024-07-18T14:00:00", "status":"finished"} |
| 121 | +] |
| 122 | +``` |
| 123 | + |
| 124 | +```csv |
| 125 | +id,name,price,date,status,capacity,quorum |
| 126 | +1,City Tour,50.0,2026-07-15T10:00:00,available,10, |
| 127 | +2,Mountain Hike,80.0,2026-07-20T08:00:00,available,,5 |
| 128 | +3,Museum Visit,30.0,2024-07-18T14:00:00,finished,, |
| 129 | +``` |
| 130 | + |
| 131 | +```xml |
| 132 | +<activities> |
| 133 | + <activity> |
| 134 | + <id>1</id> |
| 135 | + <name>City Tour</name> |
| 136 | + <price>50.0</price> |
| 137 | + <date>2026-07-15T10:00:00</date> |
| 138 | + <status>available</status> |
| 139 | + <capacity>10</capacity> |
| 140 | + </activity> |
| 141 | + <activity> |
| 142 | + <id>2</id> |
| 143 | + <name>Mountain Hike</name> |
| 144 | + <price>80.0</price> |
| 145 | + <date>2026-07-20T08:00:00</date> |
| 146 | + <status>available</status> |
| 147 | + <quorum>5</quorum> |
| 148 | + </activity> |
| 149 | + <activity> |
| 150 | + <id>3</id> |
| 151 | + <name>Museum Visit</name> |
| 152 | + <price>30.0</price> |
| 153 | + <date>2024-07-18T14:00:00</date> |
| 154 | + <status>finished</status> |
| 155 | + </activity> |
| 156 | +</activities> |
| 157 | +``` |
| 158 | + |
| 159 | +### 5.2 Bookings |
| 160 | + |
| 161 | +```json |
| 162 | +[ |
| 163 | + {"id":1, "activityId":1, "customerName":"Juan Pérez", "bookingDate":"2025-06-01T12:00:00", "status":"confirmed"}, |
| 164 | + {"id":2, "activityId":2, "customerName":"María Gómez", "bookingDate":"2025-06-02T15:30:00", "status":"confirmed"}, |
| 165 | + {"id":3, "activityId":1, "customerName":"Luis Martínez", "bookingDate":"2025-06-03T09:45:00", "status":"cancelled"} |
| 166 | +] |
| 167 | +``` |
| 168 | + |
| 169 | +```csv |
| 170 | +id,activityId,customerName,bookingDate,status |
| 171 | +1,1,Juan Pérez,2025-06-01T12:00:00,confirmed |
| 172 | +2,2,María Gómez,2025-06-02T15:30:00,confirmed |
| 173 | +3,1,Luis Martínez,2025-06-03T09:45:00,cancelled |
| 174 | +``` |
| 175 | + |
| 176 | +```xml |
| 177 | +<bookings> |
| 178 | + <booking> |
| 179 | + <id>1</id> |
| 180 | + <activityId>1</activityId> |
| 181 | + <customerName>Juan Pérez</customerName> |
| 182 | + <bookingDate>2025-06-01T12:00:00</bookingDate> |
| 183 | + <status>confirmed</status> |
| 184 | + </booking> |
| 185 | + <booking> |
| 186 | + <id>2</id> |
| 187 | + <activityId>2</activityId> |
| 188 | + <customerName>María Gómez</customerName> |
| 189 | + <bookingDate>2025-06-02T15:30:00</bookingDate> |
| 190 | + <status>confirmed</status> |
| 191 | + </booking> |
| 192 | + <booking> |
| 193 | + <id>3</id> |
| 194 | + <activityId>1</activityId> |
| 195 | + <customerName>Luis Martínez</customerName> |
| 196 | + <bookingDate>2025-06-03T09:45:00</bookingDate> |
| 197 | + <status>cancelled</status> |
| 198 | + </booking> |
| 199 | +</bookings> |
| 200 | +``` |
0 commit comments