feat: order creation #95
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/order-creation"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
PR Review: feat: order creation
Good work on implementing the order creation flow. Here are my findings:
✅ What's Good
Orderclass insrc/lib/entities/cart/order/index.tsis well-structured with clearcreateandresetCountermethods.getUserLatestOrCreatecorrectly excludes already-ordered carts usingnotExists.countItems()method — Useful guard before creating an order.pricefromint()toreal()on the product table anddiscountfromnumeric()toreal()on the order table is correct (prices need decimal precision).priceSchemaandpricePositiveSchemais a good pattern.🔍 Issues to Address
1. Unsafe type cast on counter value (Medium)
File:
src/lib/entities/cart/order/index.ts, line 21The
ordersState.valuecolumn istextin the database. Casting directly tonumberis unsafe — if the value is corrupted or not a valid number, this silently producesNaN. Consider:2. Inconsistent price validation (Low)
File:
src/routes/_schemas.tsvssrc/routes/admin/products/[categoryId]/_schemas.tsThe order creation schema uses
priceSchema(allows negative values), while admin product forms usepricePositiveSchema(requires ≥ 0). The "discount" field on the home page label says "Modifica prezzo" (Modify price) which is ambiguous — is it a discount or a final price? Consider:finalPriceordiscountAmount)pricePositiveSchemaif the value must be ≥ 03. Migration file missing trailing newline (Cosmetic)
File:
migrations/0010_curvy_phalanx.sqlThe file doesn't end with a newline character. This is a minor style issue that the formatter should catch.
4. Index creation in migration (Cosmetic)
The migration creates
product_categoryIdindex. Verify this isn't already being created by Drizzle's table definition — if it is, the migration will have a duplicate index. Looking at the table definition inproduct.ts, the index IS defined via.index(), so this could cause a conflict.ℹ️ Notes (Not blocking)
// Here we should also print receipts.inOrder.create()is fine as a placeholder.resetCounterunused: TheresetCountermethod is exported but not called anywhere. This is fine as a utility for future admin use.orders/+page.sveltehas a TODO placeholder — expected for this PR.Orderentity.✅ CI Status
format:check— ✅ Passeslint:check— ⚠️ Biome crashes on thecupsworkspace (pre-existing, unrelated to this PR)check(svelte-check) — ✅ Passes (0 errors, only pre-existing warnings)Verdict: Approved with suggestions
The core logic is sound and well-structured. The main concern is the unsafe type cast on the counter value (issue #1). The other items are lower priority.
@ -0,0 +18,4 @@const counterRow = await tx.select({ value: s.ordersState.value }).from(s.ordersState).where(eq(s.ordersState.key, COUNTER_DB_KEY))Unsafe type cast:
counterRow.valueistextfrom DB but cast directly tonumber. UseparseIntwith fallback.@ -91,0 +93,4 @@<Form form={orderForm} class="mt-auto"><NumericInput field={orderForm.fields.discount} value={0} label="Modifica prezzo" />Field labeled 'Modifica prezzo' but named 'discount' — consider renaming for clarity. Also consider using
pricePositiveSchemaif negative values aren't intended.@ -26,3 +27,7 @@ export const addProductToOrderSchema = v.lazyAsync(async (input) => {),});});This field name is confusing. 'discount' suggests a reduction, but the UI label says 'Modify price'. Clarify the intent.