Dmytro Shevchenko
@dmytro_shevchenko • 1 weeks ago
Get an AI code review that sorts every finding into blocker, major, minor or nit, gives a triggering input for each and ends with a merge verdict.
contextstackcode{{context}}{{stack}}{{code}}context: Checkout API for a D2C store, about 2,000 orders a day, MongoDB via Mongoose. Carts belong to logged-in users; auth middleware sets req.user.
stack: Node 22, Express 5, Mongoose 8
code:
```js
router.post("/cart/:id/coupon", requireAuth, async (req, res) => {
const cart = await Cart.findById(req.params.id)
const coupon = await Coupon.findOne({ code: req.body.code })
if (coupon.expiresAt < Date.now()) {
return res.status(400).json({ error: "Coupon expired" })
}
if (coupon.usedCount >= coupon.maxUses) {
return res.status(400).json({ error: "Coupon fully redeemed" })
}
cart.discount = cart.subtotal * coupon.percent / 100
cart.total = cart.subtotal - cart.discount
coupon.usedCount++
await coupon.save()
await cart.save()
res.json(cart)
})
```findById(req.params.id) never checks ownership. A logged-in user who posts to /cart//coupon changes that cart's total, and the response returns the whole cart document.`js`{ "code": "TYPO10" } makes coupon null, and coupon.expiresAt throws a TypeError, which surfaces as a 500. Add if (!coupon) return res.status(400).json({ error: "Invalid coupon" }).maxUses can be exceeded under concurrency (lines 8–15)usedCount = 99 and all pass. Do the check and increment in one operation:`js`usedCount when the order is placed, using the atomic update above.cart.save() fails validation, the use is spent and the customer gets nothing. Once MAJOR 1 is fixed this goes away. Otherwise, wrap both in a transaction.1299 * 15 / 100 = 194.85 is fine, but with paise stored as decimals you'll get values like 0.30000000000000004. Store amounts in minor units (integers) and Math.round the discount." save10" fails. Normalize with String(req.body.code ?? "").trim().toUpperCase(), and store codes uppercase.requireAuth rejects anonymous users and that Cart has a user field. If carts are keyed differently, adjust BLOCKER 1's filter.