# Flutter Integration: `close-box` now requires `transfer_order_id`

## Overview

`GET /transfer-order/close-box` used to look up the box to close by `box_name` alone. Box names (e.g. `"1-1"`, `"1-98"`) are **not unique across transfer orders** — the same name is reused on different orders — so the old endpoint could mark the wrong transfer order's box as "counted" whenever names collided. The fix requires the request to also identify which transfer order the box belongs to.

**This is a breaking API change, not an optional field.** Any request missing `transfer_order_id` will now get a `422` instead of succeeding.

## API Request Change

`GET /transfer-order/close-box`

**Before:**
```
GET /transfer-order/close-box?box_name=1-1
```

**After:**
```
GET /transfer-order/close-box?transfer_order_id=302&box_name=1-1
```

| Param | Type | Required | Notes |
|---|---|---|---|
| `transfer_order_id` | integer | **required (new)** | Must exist in `transfer_orders`. Same value already sent by `update-box`, `cache-boxes`, and `fetch-barcodes` on this screen. |
| `box_name` | string | required (unchanged) | Must exist in `transfer_order_source_boxes`. |

Response shape on success/failure is unchanged (`{"status": true, "message": "Box closed successfully."}` / `{"status": false, "message": "..."}`).

### New failure mode

If `transfer_order_id` is omitted or invalid, the request now fails validation before reaching the controller:

```json
{
  "message": "The transfer order id field is required. (and 1 more error)",
  "errors": {
    "transfer_order_id": ["The transfer order id field is required."]
  }
}
```
HTTP status `422`.

## API Integration

Wherever the app calls `close-box`, add `transferOrderId` to the call. It should already be in scope on this screen — it's the same value passed to `updateBox`/`cacheBoxes`/`fetchBarcodes`:

```dart
// Before
final response = await api.closeBox(
  boxName: boxName,
);

// After
final response = await api.closeBox(
  transferOrderId: transferOrderId, // same value already used for updateBox/fetchBarcodes on this screen
  boxName: boxName,
);
```

In the API client method itself, add the query param:

```dart
Future<Map<String, dynamic>> closeBox({
  required int transferOrderId,
  required String boxName,
}) async {
  final response = await _dio.get('/transfer-order/close-box', queryParameters: {
    'transfer_order_id': transferOrderId,
    'box_name': boxName,
  });
  return response.data;
}
```

(Adjust to whatever HTTP client/method signature this project's `ApiService` actually uses — search for `closeBox` or `close-box` in the mobile codebase to find the real call site and signature.)

## Testing Checklist

- [ ] Closing a box sends `transfer_order_id` in the query string
- [ ] Closing a box on transfer order A no longer affects a same-named box on transfer order B
- [ ] App handles a `422` from this endpoint gracefully (e.g. if an old cached screen state lacks the id)
- [ ] Regression: `update-box`, `cache-boxes`, `fetch-barcodes` still work unchanged (already sent `transfer_order_id`)

## Migration Notes

- **Not backward compatible.** Once the backend deploys this change, any app build still calling `close-box` without `transfer_order_id` will get a `422` and the box-close action will silently fail from the user's perspective (or surface as an error, depending on how the app handles validation failures).
- Coordinate release timing: ship the app update that adds `transfer_order_id` before or together with the backend deploy, not after.
- No other endpoints in this flow changed shape (`update-box`, `cache-boxes`, `fetch-barcodes` already required `transfer_order_id` and are unaffected).
