Org Web Adapter

hungryroot/jira/be_7303_evaluate_cx_skip_unskip_endpoint_strategy_dedicated_internal_cx_endpoints.org

ID
1377bbae-3dca-4f4e-9c1c-526b3133985e

BE-7303 Evaluate CX skip/unskip endpoint strategy - dedicated internal CX endpoints

- source :: https://hungryroot.atlassian.net/browse/BE-7303

- tags :: Hungryroot API Project

- epic :: EP-411 Eng Parking Lot

- sprint :: HR BE Sprint 105 HR BE Sprint 106 HR BE Sprint 107

- status :: Status - To Do

- priority :: Priority - Low

- points :: 0.5

Tasks

DONE Investigate key differences between V1 and V2 skip and unskip endpoints

workhungryrootep411sprint106be7303cxtool
ID
b7a12255-fba2-fe85-5875-3e678acb53e1

- Note taken on

[[https://app.datadoghq.com/logs?query=%28%40path%3A%22%2Fapi%2Fskip_order%2F%22%20OR%20%40path%3A%22%2Fapi%2Funskip_order%2F%22%29%20%40event%3Arequest_finished&agg_m=count&agg_m_source=base&agg_t=count&clustering_pattern_field_path=message&cols=host%2Cservice%2C%40http_host&messageDisplay=inline&refresh_mode=sliding&storage=hot&stream_sort=time%2Cdesc&viz=stream&from_ts=1772467044719&to_ts=1773763044719&live=true][Datadog table]]

TODO Create tickets for dedicated CX internal endpoints for skip and unskip

workhungryrootjiraep411sprint106be7303cxtoolapiv1

Description

Background

We had to rollback a previous change (see diff below) that attempted to move the

CX tool's skip/unskip functionality from the v2 PATCH

/api/v2/customers/{id}/orders/{id}/ endpoint to the v1 POST /api/skip_order/ and

POST /api/unskip_order/ endpoints. The rollback was needed because the v1

skip/unskip endpoints have different behavior from what CX requires (e.g.,

different validation rules, permission handling, and side effects).

The v1 endpoints (app/views/api.skip_order and app/views/api.unskip_order) use

app.services.api.delivery.skip_order / unskip_order which have different logic

from the v2 OrderDetailSerializer.update() flow (in app/rest/order.py).

Key Differences

| Concern | v1 skip_order / unskip_order | v2 OrderDetailSerializer.update() |

| Permission check | is_user_in_group(request.user, 'support') - allows support to act on other users' orders | Standard DRF permission classes |

| Skip logic | Delegates to api.skip_order() service which has its own validation, is_in_support param | Inline validation + direct model update |

| Unskip logic | Delegates to api.unskip_order() service | Inline validation + calculate_preferred_date() + shuffle check |

| is_cx_action | Passed via POST body | Passed via query param ?is_cx_action=true |

Client Usage Audit

Codebase audit (completed):

skipOrder in api.js: Exported (httpPost('/api/skip_order/', {id: orderId})) but

not imported or used anywhere in the frontend. Dead code.

postUnskipOrder in api.js: Used only in CX tool's StatusModule.jsx (currently

rolled back to use v2 PATCH).

cxSkipOrder in internal.js: Used only in CX tool's StatusModule.jsx (currently

rolled back to use v2 PATCH).

No mobile/native client references to /api/skip_order/ or /api/unskip_order/ found

in the codebase.

No other Python views reference these endpoints beyond the v1 URL registration

in app/urls/apiv1.py.

!! Datadog audit required !! The codebase audit only confirms there are no

references in our code. We must check Datadog for actual traffic to these

endpoints from mobile and web clients before making any changes:

Check request volume to POST /api/skip_order/ and POST /api/unskip_order/ in Datadog

APM

Break down by client (mobile app vs web vs CX tool) to confirm no external

consumers

If there is mobile/web client traffic, those consumers must be migrated before

any endpoint changes

Goal

We want to keep skip/unskip for CX internal to the backoffice compute. The CX

tool should use either:

A NEW CX specific v2 API with CX-appropriate behavior, OR

A dedicated internal API endpoint (under /api/internal/ or similar) purpose-built

for CX use

The v1 /api/skip_order/ and /api/unskip_order/ endpoints should NOT be the path

forward for CX -- they are customer-facing endpoints with different validation

and side-effect behavior.

Options to Evaluate

Option A: Dedicated CX skip/unskip endpoints in api-internal

Create new endpoints under the internal API (e.g., POST

/api/internal/cx_skip_order/ and POST /api/internal/cx_unskip_order/) that:

Are restricted to support group users

Use the appropriate skip/unskip logic for CX use cases

Accept is_cx_action in the POST body

Live in app/views/internal.py or a dedicated CX module

Run on backoffice compute only

Option B: Create a NEW v2 API with CX-specific behavior

Keep the current v2 PATCH approach but ensure the is_cx_action query param

properly differentiates CX behavior (e.g., bypassing certain validations that

don't apply to support actions). This already runs on backoffice compute.

Acceptance Criteria

- [ ] Check Datadog for actual traffic to /api/skip_order/ and /api/unskip_order/ from mobile and web clients

- [ ] Decide on the approach (A, B, or C)

- [ ] Confirm no external client depends on these endpoints (Datadog + codebase)

- [ ] Implement the chosen approach, keeping it on backoffice compute

- [ ] Update the CX tool frontend (StatusModule.jsx) to use the new/chosen endpoints

- [ ] Remove dead code (skipOrder export in api.js if confirmed unused)

- [ ] Add/update tests for the new endpoint(s)

Related

Rolled-back PR that attempted this migration

app/views/api.py lines 380-438 (current v1 skip/unskip)

app/rest/order.py lines 919-968 (v2 skip/unskip via OrderDetailSerializer)

app/frontend/react/src/cx_tool/customerOrders/orderDetails/StatusModule.jsx (CX

tool consumer)

BE-7294: Allow CX actions to bypass order status validation on skip/unskip