Design: Move Group Block Handling to BlockRequestsController
Date: 2026-06-12
Status: Approved
Author: Claude
1. Problem Statement
Group block handling for restaurant_id == 'all' (or blank) was incorrectly added to Api::Partner::V1::InventoriesController#block. The correct place for this behavior is Api::Partner::V1::BlockRequestsController#create. We need to:
- Revert
Api::Partner::V1::InventoriesController#blockto match themainbranch behavior (single-restaurant only). - Extend
Api::Partner::V1::BlockRequestsController#createto handle both single-restaurant and group (all/blank) block requests.
2. Goals
POST /api/partner/v1/inventories/blockonly handles single-restaurant inventory blocks, exactly as onmain.POST /api/partner/v1/block_requestshandles:- single
restaurant_id→ creates one pendingBlockAllotmentRequest restaurant_id == 'all'or blank → creates pending requests for flagged restaurants and directly blocks non-flagged restaurants
- single
- Group block operations are atomic (all-or-nothing rollback on any failure).
ChangeTrackernotifications for group blocks are moved toBlockRequestsController.
3. Architecture
┌─────────────────────────────────────┐
│ POST /api/partner/v1/block_requests │
│ BlockRequestsController#create │
└──────────────┬──────────────────────┘
│
┌───────┴───────┐
│ │
restaurant_id restaurant_id
single 'all' / blank
│ │
▼ ▼
SubmitService GroupSubmitService
│ │
▼ ▼
pending request pending requests + direct blocks
4. Components
4.1 Api::Partner::V1::BlockRequestsController#create
- Permits
restaurant_idalong with existing params. - If
restaurant_idis'all'or blank:- Calls
BlockRequest::GroupSubmitServicewithrestaurantsfrom the current staff. - On success, calls
ChangeTracker#track_block_inventoryand#notify_managersif any direct block occurred. - Renders JSON using
Api::Partner::BlockAllotmentRequestSerializerwithdata(array of block requests) plus top-leveldirect_block_ids.
- Calls
- Otherwise:
- Calls
BlockRequest::SubmitServicewith the single restaurant. - Renders JSON using
Api::Partner::BlockAllotmentRequestSerializerwithdata(single block request), status:created.
- Calls
4.2 BlockRequest::GroupSubmitService
- Accepts
restaurants,staff, andparams. - Partitions restaurants into:
- flagged (and start_date >= 2 days away) → pending block requests
- non-flagged (or start_date < 2 days away) → direct inventory block
- Wraps the entire operation in an
ActiveRecord::Base.transactionto guarantee all-or-nothing behavior. - Returns a
ServiceResultwith:block_requests: array of created pending requestsdirect_block_ids: array of restaurant IDs directly blockeddirect_message: combined success message from direct blocks
4.3 BlockRequest::SubmitService
- No functional changes.
- Continues to validate flagged status, date range, reason, and duplicates.
- Creates a single pending
BlockAllotmentRequest.
4.4 Api::Partner::V1::InventoriesController#block
- Reverted to
mainbranch implementation. - Removes
handle_group_blockprivate method. - Behavior for single restaurant remains:
- If flagged and date >= 2 days → create pending request
- Else → direct block via
PartnerService::Inventories::BlockService
5. Data Flow
Single restaurant
- Client posts to
/api/partner/v1/block_requestswithrestaurant_id: 123. - Controller calls
BlockRequest::SubmitService. - Service validates and creates pending
BlockAllotmentRequest. - Controller renders
{ data: serialized_request }, status201.
Group block
- Client posts to
/api/partner/v1/block_requestswithrestaurant_id: 'all'(or omitted). - Controller resolves all restaurants accessible to the current staff.
- Controller calls
BlockRequest::GroupSubmitService. - Service partitions restaurants and processes flagged/non-flagged paths inside a transaction.
- On success:
- Controller calls
ChangeTracker#track_block_inventoryand#notify_managersifdirect_block_idsis non-empty. - Controller renders
{ data: [...serialized_requests], direct_block_ids: [...] }, status201.
- Controller calls
- On any failure, transaction rolls back and controller renders
422with error messages.
6. Error Handling
| Scenario | HTTP Status | Response |
|---|---|---|
| Single restaurant validation fails | 422 | { errors: [...], message: '...' } |
| Group block: any restaurant fails | 422 | { errors: [...], message: '...' } (all rolled back) |
| Group block: all succeed | 201 | { data: [...], direct_block_ids: [...] } |
| Restaurant not found / not authorized | 404 / 422 | Existing error handling |
7. Testing Plan
Request specs (spec/requests/api/partner/v1/block_requests_spec.rb)
- Add context
POST /api/partner/v1/block_requests with restaurant_id == 'all':- all flagged restaurants → creates pending requests for all
- mixed flagged/non-flagged → pending for flagged, direct block for non-flagged
- all non-flagged → direct blocks, no pending requests
- partial failure → no side effects (rollback)
- Add context
POST /api/partner/v1/block_requests with blank restaurant_id:- behaves like
'all'
- behaves like
Request specs (spec/requests/api/partner/v1/inventories_spec.rb)
- Remove all group-block test contexts.
- Keep single-restaurant block tests matching
mainbranch behavior.
Service specs (spec/services/block_request/group_submit_service_spec.rb)
- Add test confirming entire operation rolls back on any failure.
- Update existing tests if transaction wrapping changes assertions around counts.
8. Files to Modify
app/controllers/api/partner/v1/block_requests_controller.rbapp/controllers/api/partner/v1/inventories_controller.rbapp/services/block_request/group_submit_service.rbspec/requests/api/partner/v1/block_requests_spec.rbspec/requests/api/partner/v1/inventories_spec.rbspec/services/block_request/group_submit_service_spec.rb
9. Out of Scope
- No changes to routes.
- No changes to
BlockRequest::SubmitServicebehavior. - No UI/frontend changes.