feat: [CIT-5181] show real copy when the basket is locked by an in-flight checkout - #7266
Draft
JoeTravisKiva wants to merge 2 commits into
Draft
JoeTravisKiva wants to merge 2 commits into
JoeTravisKiva wants to merge 2 commits into
Conversation
The backend now refuses basket edits while the lender's own checkout is running (CIT-4190), returning checkout_in_progress from the loan reservation path or shop.checkoutInProgress from the donation, Kiva Card and credit paths. Both surfaced as generic error copy, and the add-to- basket paths routed them through handleInvalidBasket, which deletes the basket cookie and reloads -- wrong here, since the basket is busy rather than broken. Adds isCheckoutInProgress, getBasketErrorCode and getBasketErrorMessage to basketUtils, and wires them through the add-to-basket, resize, remove and donation paths. The copy is a placeholder pending design/content review; it lives in one constant so swapping it is a one-line change. Skips Sentry for these codes where the call site owns the reporting -- expected contention, not a defect. Note setLendAmount captures before it rejects, so its two callers still report. Also fixes a latent bug in LoanPrice and RemoveBasketItem, which read a top-level `code` off GraphQL errors where the code lives under extensions.code, so their not_all_shared_added checks never fired. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Conflicts: # test/unit/specs/components/Checkout/DonationItem.spec.js
mcstover
approved these changes
Sep 16, 2026
mcstover
left a comment
Collaborator
There was a problem hiding this comment.
I think this is good and covers the stuff in this repo so a different PR could hold the updates from kv-shop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CIT-5181 — follow-up to CIT-4190 / CIT-5194.
Why
The backend now refuses basket edits while the lender's own checkout is still running. That's correct, but it turned a silent data corruption into a visible failure, and the lender got generic error copy.
Worse, the add-to-basket paths routed these failures through
hasBasketExpired()→handleInvalidBasket(), which deletes thekvbsktcookie and reloads the page. The basket is busy, not broken, so that's the wrong response. Avoiding exactly that is why CIT-5194 stopped these failures reportingshop.invalidBasketId.Two codes mean the same thing and are treated identically:
checkout_in_progressupdateLoanReservation)shop.checkoutInProgressWhat
Three helpers in
src/util/basketUtils.js, next to the existinghasBasketExpired:isCheckoutInProgress(code)— matches both codesgetBasketErrorCode(error)— readsextensions.code, falls back tocodegetBasketErrorMessage(error)— lender-facing copy, overriding the backend stringWired through add-to-basket (
borrower-profile-exp-mixin,KvClassicLoanCardContainer,KivaClassicBasicLoanCard,LendButton), resize (LoanPrice), remove (RemoveBasketItem), donation (DonationItem) andcheckout-utils-mixin'sshowCheckoutError.Notes for review
CHECKOUT_IN_PROGRESS_MESSAGE) so swapping it is a one-line change. The lock self-heals after 300s, so the copy deliberately doesn't imply a permanent state.setLendAmountcaptures before it rejects, so its two callers still report regardless; only the redundant second capture is skipped.LoanPrice.vueandRemoveBasketItem.vuedestructured a top-levelcodeoff GraphQL errors, where the code actually lives underextensions.code. Theirnot_all_shared_addedchecks have therefore never fired. Routing throughgetBasketErrorCodefixes that, which means that branch (an 8s delayed reload) can now actually trigger.Testing
332 test files / 4991 tests passing, lint clean. New specs cover both codes at each call site, each paired with a control asserting an expired-basket error still clears the basket — so the tests prove the branch discriminates rather than always passing.
Deliberately out of scope
checkoutTransactionId/checkoutRequestedAtplumbed into the basket queries — nothing queries them today — plus a freshness check against the 300s TTL.eb62855cawas a one-string fix applied across all four, so the pull is real — but extraction would push$showTipMsg/$kvTrackEventintobasketUtils.js, which today takes only data. Wants auseAddToBasket()composable and its own ticket.AdaptiveMicroLoanCard,AppealBannerCircularContainer,CheckoutPage:1293,DepositIncentiveUpsell,LendCta,CCLandingPage.ProcessInstantLendingandLendButton2additionally Sentry-capture, so contention there will page someone.TeamAttribution/DonateRepaymentsTogglehitupdateLoanReservationTeam/updateLoanReservationDonateRepayments— pending backend confirmation on whether those take the same lock.🤖 Generated with Claude Code