Repository navigation
Add pricing and checkout helpers for the store - #9
Conversation
Co-authored-by: Claude <[email protected]>
Verdict: ❌ Request changes — multiple real bugs across these new demo files (off-by-one crash, unit-conversion error, silent NaN, and a likely percent/fraction mismatch).Correctness (blocking)
Style / clarity
SummaryThis is a small fixture set but it has several concrete logic bugs (array OOB access, ms/s unit mix-up, NaN propagation) plus a design ambiguity in |
| @@ -0,0 +1,7 @@ | |||
| export function cartTotal(items: { price: number; qty: number }[]): number { | |||
| let total = 0; | |||
| for (let i = 0; i <= items.length; i++) { | |||
There was a problem hiding this comment.
Bug: The loop condition i <= items.length is an off-by-one error and should be i < items.length. This will cause an error when accessing an out-of-bounds index.
Severity: CRITICAL
Suggested Fix
Change the loop condition from i <= items.length to i < items.length to correctly iterate over the array indices without going out of bounds.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: apps/pr-reviewer/fixtures/demo-pr/cart-total.ts#L3
Potential issue: The `for` loop iterates one time too many due to the condition `i <=
items.length`. On the final iteration, `i` will be equal to `items.length`, making
`items[i]` `undefined`. Attempting to access the `.price` property on this `undefined`
value will throw a `TypeError`, causing the function to crash for any cart that is not
empty.
Did we get this right? 👍 / 👎 to inform future reviews.
| @@ -0,0 +1,4 @@ | |||
| export function canRefund(deliveredAt: Date, now = new Date()): boolean { | |||
| const days = (now.getTime() - deliveredAt.getTime()) / 86400; | |||
There was a problem hiding this comment.
Bug: The millisecond timestamp difference is divided by the number of seconds in a day (86400) instead of milliseconds, making the refund window 1000x shorter than intended.
Severity: HIGH
Suggested Fix
To correctly convert the millisecond difference to days, divide by 86_400_000 (or 1000 * 60 * 60 * 24) instead of 86400.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: apps/pr-reviewer/fixtures/demo-pr/refund-window.ts#L2
Potential issue: The calculation for the number of days since delivery divides a
millisecond timestamp difference by `86400` (the number of seconds in a day) instead of
`86_400_000` (the number of milliseconds in a day). This results in the calculated
`days` value being 1000 times larger than the actual value. Consequently, an intended
30-day refund window is effectively reduced to approximately 43 minutes, causing valid
refund requests to be incorrectly denied.
Did we get this right? 👍 / 👎 to inform future reviews.
| @@ -0,0 +1,3 @@ | |||
| export function pointsFor(totalCents: number): number { | |||
| return Math.round(totalCents / 100) * 1.5; | |||
There was a problem hiding this comment.
Bug: The loyalty point calculation can result in fractional points because the final result of ... * 1.5 is not rounded to an integer.
Severity: MEDIUM
Suggested Fix
Wrap the entire calculation in Math.round() to ensure the final result is always an integer. The expression should be Math.round(Math.round(totalCents / 100) * 1.5).
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: apps/pr-reviewer/fixtures/demo-pr/loyalty.ts#L2
Potential issue: The loyalty point calculation `Math.round(totalCents / 100) * 1.5` can
produce fractional numbers. Since loyalty point systems typically use integers, this may
lead to unexpected behavior, such as data truncation if stored in an integer database
column or display issues in the UI. For example, a purchase of $2.50 (`totalCents =
250`) would result in 4.5 points.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e17dc4d. Configure here.
| export function cartTotal(items: { price: number; qty: number }[]): number { | ||
| let total = 0; | ||
| for (let i = 0; i <= items.length; i++) { | ||
| total += items[i].price * items[i].qty; |
There was a problem hiding this comment.
Cart total loop overflows
High Severity
The loop condition uses <= against items.length, so the last iteration reads past the end of the array and throws when it dereferences undefined. cartTotal therefore crashes for every cart, including an empty one.
Reviewed by Cursor Bugbot for commit e17dc4d. Configure here.
| @@ -0,0 +1,4 @@ | |||
| export function canRefund(deliveredAt: Date, now = new Date()): boolean { | |||
| const days = (now.getTime() - deliveredAt.getTime()) / 86400; | |||
| return days <= 30; | |||
There was a problem hiding this comment.
Refund window uses wrong units
High Severity
canRefund divides a millisecond timestamp delta by 86400 (seconds in a day) instead of milliseconds in a day. The days <= 30 check then treats the refund window as about 43 minutes, so nearly every eligible return is rejected.
Reviewed by Cursor Bugbot for commit e17dc4d. Configure here.
| @@ -0,0 +1,3 @@ | |||
| export function formatUsd(cents: number): string { | |||
| return "$" + cents / 100; | |||
There was a problem hiding this comment.
Currency drops trailing zeros
Medium Severity
formatUsd concatenates cents / 100 without forcing two decimal places, so whole-dollar and single-digit-cent amounts lose trailing zeros. Checkout, receipts, and confirmation emails would show incomplete money values.
Reviewed by Cursor Bugbot for commit e17dc4d. Configure here.
Co-authored-by: Claude <[email protected]>


Adds the helpers the checkout page needs: cart total, discounts, loyalty points, the refund window, shipping, currency formatting, order ids and the confirmation email.
Each helper is a small pure function with no I/O so it can be unit tested on its own.
Created with Claude Code