# Instructions

- Following Playwright test failed.
- Explain why, be concise, respect Playwright best practices.
- Provide a snippet of code with the fix, if possible.

# Test info

- Name: src/manager/tests/e2e/booking/booking-adjustment-delete.spec.ts >> deletes the adjustment from the actions menu
- Location: src/manager/tests/e2e/booking/booking-adjustment-delete.spec.ts:42:5

# Error details

```
Error: Failed to fetch booking 14515377846716 via API: 404 {
    "message": "The route api/v1/booking/14515377846716 could not be found.",
    "exception": "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException",
    "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/AbstractRouteCollection.php",
    "line": 44,
    "trace": [
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/CompiledRouteCollection.php",
            "line": 164,
            "function": "handleMatchedRoute",
            "class": "Illuminate\\Routing\\AbstractRouteCollection",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 777,
            "function": "match",
            "class": "Illuminate\\Routing\\CompiledRouteCollection",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 764,
            "function": "findRoute",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 753,
            "function": "dispatchToRoute",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
            "line": 200,
            "function": "dispatch",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 180,
            "function": "{closure:Illuminate\\Foundation\\Http\\Kernel::dispatchToRouter():197}",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/livewire/livewire/src/Features/SupportDisablingBackButtonCache/DisableBackButtonCacheMiddleware.php",
            "line": 19,
            "function": "{closure:Illuminate\\Pipeline\\Pipeline::prepareDestination():178}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 219,
            "function": "handle",
            "class": "Livewire\\Features\\SupportDisablingBackButtonCache\\DisableBackButtonCacheMiddleware",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
            "line": 21,
            "function": "{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():194}:195}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php",
            "line": 31,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 219,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
            "line": 21,
            "function": "{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():194}:195}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php",
            "line": 51,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 219,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TrimStrings",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php",
            "line": 27,
            "function": "{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():194}:195}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 219,
            "function": "handle",
            "class": "Illuminate\\Http\\Middleware\\ValidatePostSize",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php",
            "line": 110,
            "function": "{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():194}:195}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 219,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php",
            "line": 74,
            "function": "{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():194}:195}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 219,
            "function": "handle",
            "class": "Illuminate\\Http\\Middleware\\HandleCors",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php",
            "line": 58,
            "function": "{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():194}:195}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 219,
            "function": "handle",
            "class": "Illuminate\\Http\\Middleware\\TrustProxies",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php",
            "line": 22,
            "function": "{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():194}:195}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 219,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\InvokeDeferredCallbacks",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePathEncoding.php",
            "line": 28,
            "function": "{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():194}:195}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 219,
            "function": "handle",
            "class": "Illuminate\\Http\\Middleware\\ValidatePathEncoding",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 137,
            "function": "{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():194}:195}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
            "line": 175,
            "function": "then",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
            "line": 144,
            "function": "sendRequestThroughRouter",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/octane/src/ApplicationGateway.php",
            "line": 36,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/octane/src/Worker.php",
            "line": 84,
            "function": "handle",
            "class": "Laravel\\Octane\\ApplicationGateway",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/octane/bin/roadrunner-worker",
            "line": 56,
            "function": "handle",
            "class": "Laravel\\Octane\\Worker",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/bin/roadrunner-worker",
            "line": 119,
            "function": "include"
        }
    ]
}
```

# Test source

```ts
  1   | import {
  2   |   fromBookingCreateApiResponse,
  3   |   toBookingAdjustmentApiPayload,
  4   |   toBookingCreateApiPayload,
  5   |   toBookingPriceChangeApiPayload,
  6   | } from '@/manager/modules/booking/booking-mappers';
  7   | import {
  8   |   BookingAdjustmentData,
  9   |   BookingCreateApiResponse,
  10  |   BookingCreateData,
  11  |   BookingPriceChange,
  12  |   BookingShowApiResponse,
  13  | } from '@/manager/modules/booking/booking-types';
  14  | import { Booking } from '@/shared/types/booking-types';
  15  | import { isModernBillingMode } from '@/shared/utils/billing-utils';
  16  | import { APIRequestContext } from '@playwright/test';
  17  | 
  18  | // The manager API serves bookings at /v1/booking; the billing API (modern Kinnovis billing) serves them at
  19  | // /api/v1/booking. A BookingApiClient bundles the request context with its matching base path so create and
  20  | // cancel hit the right host without each call re-deriving the mode.
  21  | export interface BookingApiClient {
  22  |   request: APIRequestContext;
  23  |   basePath: string;
  24  | }
  25  | 
  26  | const managerBookingBasePath = '/v1/booking';
  27  | const billingBookingBasePath = '/api/v1/booking';
  28  | 
  29  | export function resolveBookingApiClient(
  30  |   managerApiRequest: APIRequestContext,
  31  |   billingApiRequest: APIRequestContext
  32  | ): BookingApiClient {
  33  |   return isModernBillingMode()
  34  |     ? { request: billingApiRequest, basePath: billingBookingBasePath }
  35  |     : { request: managerApiRequest, basePath: managerBookingBasePath };
  36  | }
  37  | 
  38  | export async function createBookingViaApi(client: BookingApiClient, data: BookingCreateData): Promise<Booking> {
  39  |   const response = await client.request.post(client.basePath, {
  40  |     data: toBookingCreateApiPayload(data),
  41  |   });
  42  | 
  43  |   if (!response.ok()) {
  44  |     throw new Error(`Failed to create booking via API: ${response.status()} ${await response.text()}`);
  45  |   }
  46  | 
  47  |   const body = (await response.json()) as BookingCreateApiResponse;
  48  | 
  49  |   return fromBookingCreateApiResponse(body, data);
  50  | }
  51  | 
  52  | export async function createBookingPriceChangeViaApi(
  53  |   client: BookingApiClient,
  54  |   bookingIds: number[],
  55  |   priceChange: BookingPriceChange
  56  | ): Promise<void> {
  57  |   const response = await client.request.post(`${client.basePath}/price-change`, {
  58  |     data: toBookingPriceChangeApiPayload(priceChange, bookingIds),
  59  |   });
  60  | 
  61  |   if (!response.ok()) {
  62  |     throw new Error(
  63  |       `Failed to create price change for bookings ${bookingIds} via API: ` +
  64  |         `${response.status()} ${await response.text()}`
  65  |     );
  66  |   }
  67  | }
  68  | 
  69  | export async function createBookingAdjustmentViaApi(
  70  |   client: BookingApiClient,
  71  |   booking: Booking,
  72  |   adjustment: BookingAdjustmentData
  73  | ): Promise<void> {
  74  |   const bookingUpdatedAt = await getBookingUpdatedAtViaApi(client, booking.id);
  75  | 
  76  |   const response = await client.request.post(`${client.basePath}/${booking.id}/adjustment`, {
  77  |     data: toBookingAdjustmentApiPayload(booking, adjustment, bookingUpdatedAt),
  78  |   });
  79  | 
  80  |   if (!response.ok()) {
  81  |     throw new Error(
  82  |       `Failed to create adjustment for booking ${booking.id} via API: ${response.status()} ${await response.text()}`
  83  |     );
  84  |   }
  85  | }
  86  | 
  87  | async function getBookingUpdatedAtViaApi(client: BookingApiClient, id: number): Promise<string> {
  88  |   const response = await client.request.get(`${client.basePath}/${id}`);
  89  | 
  90  |   if (!response.ok()) {
> 91  |     throw new Error(`Failed to fetch booking ${id} via API: ${response.status()} ${await response.text()}`);
      |           ^ Error: Failed to fetch booking 14515377846716 via API: 404 {
  92  |   }
  93  | 
  94  |   const body = (await response.json()) as BookingShowApiResponse;
  95  |   const updatedAt = body.data.updated_at ?? body.data.updatedAt;
  96  | 
  97  |   if (updatedAt == null) {
  98  |     throw new Error(`Booking ${id} response contains neither updated_at nor updatedAt`);
  99  |   }
  100 | 
  101 |   return updatedAt;
  102 | }
  103 | 
  104 | export async function cancelBookingAtPeriodEndViaApi(client: BookingApiClient, id: number): Promise<void> {
  105 |   const response = await client.request.put(`${client.basePath}/${id}/cancel`, {
  106 |     data: { type: 'end_of_period', cancel_on_date: null },
  107 |   });
  108 | 
  109 |   if (!response.ok()) {
  110 |     throw new Error(
  111 |       `Failed to cancel booking ${id} at period end via API: ${response.status()} ${await response.text()}`
  112 |     );
  113 |   }
  114 | }
  115 | 
  116 | export async function cancelBookingNowViaApi(client: BookingApiClient, id: number): Promise<void> {
  117 |   const body = { data: { type: 'now', cancel_on_date: null } };
  118 | 
  119 |   const cancel = await client.request.put(`${client.basePath}/${id}/cancel`, body);
  120 | 
  121 |   if (cancel.ok() || cancel.status() === 404) {
  122 |     return;
  123 |   }
  124 | 
  125 |   const postpone = await client.request.put(`${client.basePath}/${id}/cancel-postpone`, body);
  126 | 
  127 |   if (postpone.ok() || postpone.status() === 404) {
  128 |     return;
  129 |   }
  130 | 
  131 |   throw new Error(
  132 |     `Failed to cancel booking ${id} via API: cancel ${cancel.status()}, ` +
  133 |       `postpone ${postpone.status()} ${await postpone.text()}`
  134 |   );
  135 | }
  136 | 
```