Repository navigation
fix: 404 unresolvable deal_id and quote_id on order create - #71
Conversation
|
Heads up on sequencing, not a concern with the fix itself — your composition reasoning in the description checks out (verified independently: an empty/None `deal_id` never reaches your `storage.get_deal` lookup, so #65's `deal_id_required` and this PR's `deal_not_found` don't collide at runtime). #65 is about to merge (Siraj + atc964 signed off, pushed the last fix). Both PRs insert a block at the identical spot in `create_change_request` — right after the order-exists check, before building diffs — so once #65 lands this branch will hit a literal (mechanical, not logical) merge conflict there on rebase. Nothing to redesign, just flagging so it's not a surprise: the two checks compose in either order (`if not deal_id: 400` then `if deal_id: ...404`, or vice versa), so resolving it should just mean keeping both blocks back to back. |
There was a problem hiding this comment.
Conflicts with
mainnow that #65 landed (both touch the samedeal_idcheck in
create_change_request) — needs a rebase. The two checks compose cleanly once ordered right:
#65'sdeal_id_required(400, missing/empty) must run before #71'sdeal_not_found(404,
present-but-unknown), since an emptydeal_idhas nothing to resolve:deal_id = order.get("deal_id") if not deal_id: raise HTTPException( status_code=400, detail={"error": "deal_id_required", "message": f"Order '{request.order_id}' has no deal_id and cannot be changed."}, ) # A non-empty deal_id on the order must still resolve. deal = await storage.get_deal(deal_id) if not deal: raise HTTPException( status_code=404, detail={"error": "deal_not_found", "message": f"Deal '{deal_id}' not found."}, )One test needs a one-line fix too:
test_unresolvable_deal_id_does_not_create_pending_cr's
payload predates #64's requiredidempotency_keyand 422s before reaching thedeal_not_found
path it's testing. Add"idempotency_key": "idem-orphan-deal-1"to that payload.Verified both changes together locally - unit + integration passed (0 failed), including
both #65's and #71's own test scenarios side by side. Happy to re-review once rebased.
|
Updated the branch against main. Missing deal IDs still return |
Sirajmx
left a comment
There was a problem hiding this comment.
Thanks @jaanijuk for filing #68 and #70 — both reproduce exactly and are closed by this fix. And
thanks @aleksUIX for already merging currentmaininto this branch and resolving the conflict
before I even got to re-check it — it fast-forwards cleanly now, zero conflicts. Thedeal_id
collision I'd flagged earlier is resolved correctly:create_orderkeeps
deal_id/quote_idoptional (matches #101's owncreate_ordersemantics), while
create_change_requestrequires an existing order to already have adeal_id(400
deal_id_required) before checking whether it resolves (404deal_not_found) — two legitimately
different rules for two different operations, not a contradiction.Verified all four claimed behaviors live, independently: omitted ids still draft an order; an
unknowndeal_idon create 404sdeal_not_foundwith nothing persisted (closes #68); an unknown
quote_id404squote_not_found(closes #70); a change request against a booked order whose
deal_idpoints nowhere 404sdeal_not_foundwith no CR record written — the actual #68
scenario (a phantom reference reachingpending_approvalwith emptyvalidation_errors),
confirmed closed. Also sanity-checked the composed rule holds: an order with nodeal_idat all
still correctly 400sdeal_id_requiredon a change request, not swallowed by the new check.Touched tests: 76/76 passed. Full suite: 1670 passed. Ruff clean.
Cross-repo: zero impact, confirmed by grep — buyer-agent only ever reads order status
(GET /api/v1/orders/{id},/history); it never creates orders or files change requests against
the seller at all.Scope is right where it should be: doesn't check a resolvable
quote_idactually belongs to the
givendeal_id(explicitly flagged as untested), and doesn't touch GAM reporting's consumption
oforder["deal_id"]— reasonable, since refusing unknown ids at creation means new orders can't
feed that path a phantom reference going forward. Approving.
) generic-api-key flagged the literal fixture string "idem-orphan-deal-1" in test_unresolvable_deal_id_does_not_create_pending_cr (PR #71) for sitting next to a key named idempotency_key. Low entropy (3.57), not a credential. Allowlisted per CONTRIBUTING.md's documented gitleaks:allow convention, same as the existing one at line 650.
Summary
Fixes #68 and #70.
POST /api/v1/orderswrotedeal_idandquote_idstraight through. An unknowndeal_idpersisted as a draft; a change request against that order then inherited the reference and reachedpending_approvalat material severity withvalidation_errorsempty. An unknownquote_iddid the same on a valid deal, so the order's quote disagreed with the deal's.The adjacent hop already resolves its parent:
POST /api/v1/dealsreturns404 quote_not_foundfor the same missing quote.GET /api/v1/deals/{id}returns404 deal_not_found. Orders now match that contract.Omitted / null ids stay allowed. An order can still be drafted before commercial terms exist. A provided id must already be in storage.
Fix
In
create_order, afterget_storage():deal_id→storage.get_deal; miss →404 deal_not_found(same detail asget_deal)quote_id→storage.get_quote; miss →404 quote_not_found(same detail asbook_deal/get_quote)For orders already stored with a phantom
deal_id(the #68 change-request path),create_change_requestdoes the same lookup after the order exists and before classifying severity or writing a CR. Empty /Noneis left alone so this does not collide with #65 (deal_id_requiredfor dealless orders).Out of scope (deliberate)
quote_idbelongs to the given deal (POST /api/v1/orders accepts and persists an unresolvable quote_id for a valid deal #70 explicitly untested).None→""write-side normalization, nodeal_id_required400. Those PRs compose: fix: reject change requests for dealless orders #65 rejects missing ids, this rejects present-but-unknown ids.gam_reporting_serviceconsumption oforder["deal_id"]). Once create refuses unknown ids, new orders cannot feed that path a phantom reference.Test plan
test_create_order_returns_draft)deal_id→ 404deal_not_found, no order row (POST /api/v1/orders accepts an unresolvable deal_id, and the reference propagates into a material change request #68 curl)quote_id→ 404quote_not_found, no order row (POST /api/v1/orders accepts and persists an unresolvable quote_id for a valid deal #70, including with a known deal)deal_idis not in storage → 404deal_not_found, no CR record, neverpending_approvalwith emptyvalidation_errorsuv run --locked ruff check src/andruff format --checkcleanCloses #68
Closes #70