@mohasinac/appkit 4.41.12 → 4.41.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/server/features/auctions/actions.js +1 -1
- package/dist/_internal/server/features/cart/actions.js +4 -4
- package/dist/_internal/server/features/events/actions.js +2 -2
- package/dist/_internal/server/features/history/actions.js +2 -2
- package/dist/_internal/server/features/lottery/actions.js +1 -1
- package/dist/_internal/server/features/orders/actions.js +5 -5
- package/dist/_internal/server/features/pre-orders/actions.js +1 -1
- package/dist/_internal/server/features/promotions/actions.js +1 -1
- package/dist/_internal/server/features/reviews/actions.js +3 -3
- package/dist/_internal/server/features/wishlist/actions.js +3 -3
- package/dist/features/admin/components/AdminOrdersView.js +29 -3
- package/dist/features/seller/components/SellerOrdersView.js +28 -4
- package/dist/features/tester/seed-data/authored/buying__order-detail-actions.js +17 -3
- package/dist/seed/orders-seed-data.js +19 -1
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ import { assertAuctionActive, assertBidAmount, assertNotAuctionOwner, shouldAuto
|
|
|
8
8
|
import { ValidationError } from "../../../shared/errors/index";
|
|
9
9
|
export async function placeBidAction(input) {
|
|
10
10
|
return wrapAction(async () => {
|
|
11
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
11
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
12
12
|
const parsed = placeBidActionSchema.safeParse(input);
|
|
13
13
|
if (!parsed.success)
|
|
14
14
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid bid input");
|
|
@@ -7,7 +7,7 @@ import { upsertCartItem, mergeGuestItems } from "./service";
|
|
|
7
7
|
import { ValidationError } from "../../../shared/errors/index";
|
|
8
8
|
export async function addToCartAction(input) {
|
|
9
9
|
return wrapAction(async () => {
|
|
10
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
10
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
11
11
|
const parsed = addToCartSchema.safeParse(input);
|
|
12
12
|
if (!parsed.success)
|
|
13
13
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid cart input");
|
|
@@ -17,7 +17,7 @@ export async function addToCartAction(input) {
|
|
|
17
17
|
}
|
|
18
18
|
export async function removeFromCartAction(input) {
|
|
19
19
|
return wrapAction(async () => {
|
|
20
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
20
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
21
21
|
const parsed = removeFromCartSchema.safeParse(input);
|
|
22
22
|
if (!parsed.success)
|
|
23
23
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid input");
|
|
@@ -27,14 +27,14 @@ export async function removeFromCartAction(input) {
|
|
|
27
27
|
}
|
|
28
28
|
export async function clearCartAction() {
|
|
29
29
|
return wrapAction(async () => {
|
|
30
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
30
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
31
31
|
await cartRepository.clearCart(user.uid);
|
|
32
32
|
return { success: true };
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
export async function mergeGuestCartAction(input) {
|
|
36
36
|
return wrapAction(async () => {
|
|
37
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
37
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
38
38
|
const parsed = mergeGuestCartSchema.safeParse(input);
|
|
39
39
|
if (!parsed.success)
|
|
40
40
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid cart data");
|
|
@@ -36,7 +36,7 @@ export async function updateEventAction(eventId, input) {
|
|
|
36
36
|
}
|
|
37
37
|
export async function registerForEventAction(input) {
|
|
38
38
|
return wrapAction(async () => {
|
|
39
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
39
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
40
40
|
const parsed = registerForEventSchema.safeParse(input);
|
|
41
41
|
if (!parsed.success)
|
|
42
42
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid registration input");
|
|
@@ -72,7 +72,7 @@ export async function registerForEventAction(input) {
|
|
|
72
72
|
}
|
|
73
73
|
export async function cancelEventRegistrationAction(entryId) {
|
|
74
74
|
return wrapAction(async () => {
|
|
75
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
75
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
76
76
|
const entry = await eventEntryRepository.findById(entryId);
|
|
77
77
|
if (!entry || entry.userId !== user.uid) {
|
|
78
78
|
throw new ValidationError("Registration not found or does not belong to you");
|
|
@@ -4,7 +4,7 @@ import { requireRoleUser } from "../../../../providers/auth-firebase/helpers";
|
|
|
4
4
|
import { historyRepository, } from "../../../../repositories";
|
|
5
5
|
export async function trackProductViewAction(productId, productType, productSnapshot) {
|
|
6
6
|
return wrapAction(async () => {
|
|
7
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
7
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
8
8
|
await historyRepository.track(user.uid, {
|
|
9
9
|
productId,
|
|
10
10
|
productType,
|
|
@@ -14,7 +14,7 @@ export async function trackProductViewAction(productId, productType, productSnap
|
|
|
14
14
|
}
|
|
15
15
|
export async function mergeGuestHistoryAction(guestItems) {
|
|
16
16
|
return wrapAction(async () => {
|
|
17
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
17
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
18
18
|
return historyRepository.merge(user.uid, guestItems);
|
|
19
19
|
});
|
|
20
20
|
}
|
|
@@ -28,7 +28,7 @@ function isDrawWindowOpen(config) {
|
|
|
28
28
|
export async function submitLotteryPullAction(input) {
|
|
29
29
|
return wrapAction(async () => {
|
|
30
30
|
// Auth — must be logged in
|
|
31
|
-
const user = await requireRoleUser(["buyer", "seller", "admin", "moderator", "employee"]);
|
|
31
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin", "moderator", "employee"]);
|
|
32
32
|
const parsed = submitLotteryPullSchema.safeParse(input);
|
|
33
33
|
if (!parsed.success) {
|
|
34
34
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid lottery pull input");
|
|
@@ -18,7 +18,7 @@ import { normalizeError } from "../../../../errors/normalize";
|
|
|
18
18
|
import { serverLogger } from "../../../../monitoring";
|
|
19
19
|
export async function createOrderAction(input) {
|
|
20
20
|
return wrapAction(async () => {
|
|
21
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
21
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
22
22
|
const parsed = createOrderSchema.safeParse(input);
|
|
23
23
|
if (!parsed.success)
|
|
24
24
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid order input");
|
|
@@ -31,7 +31,7 @@ export async function createOrderAction(input) {
|
|
|
31
31
|
}
|
|
32
32
|
export async function cancelOrderAction(input) {
|
|
33
33
|
return wrapAction(async () => {
|
|
34
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
34
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
35
35
|
const parsed = cancelOrderSchema.safeParse(input);
|
|
36
36
|
if (!parsed.success)
|
|
37
37
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid input");
|
|
@@ -50,7 +50,7 @@ export async function cancelOrderAction(input) {
|
|
|
50
50
|
*/
|
|
51
51
|
export async function requestReturnAction(input) {
|
|
52
52
|
return wrapAction(async () => {
|
|
53
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
53
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
54
54
|
const parsed = returnRequestSchema.safeParse(input);
|
|
55
55
|
if (!parsed.success)
|
|
56
56
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid input");
|
|
@@ -161,7 +161,7 @@ function notifyAdminsOfPaymentProof(order) {
|
|
|
161
161
|
}
|
|
162
162
|
export async function attachPaymentProofAction(orderId, proof) {
|
|
163
163
|
return wrapAction(async () => {
|
|
164
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
164
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
165
165
|
const order = await orderRepository.findById(orderId);
|
|
166
166
|
if (!order)
|
|
167
167
|
throw new OrderNotFoundError(orderId);
|
|
@@ -350,7 +350,7 @@ export async function adminRejectPaymentAsFraudAction(orderId, note) {
|
|
|
350
350
|
*/
|
|
351
351
|
export async function raiseOrderDisputeAction(orderId, reason) {
|
|
352
352
|
return wrapAction(async () => {
|
|
353
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
353
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
354
354
|
if (!reason.trim())
|
|
355
355
|
throw new ValidationError(REASON_REQUIRED_MSG);
|
|
356
356
|
const order = await orderRepository.findById(orderId);
|
|
@@ -7,7 +7,7 @@ import { assertPreOrderAvailable, computeDeposit } from "./service";
|
|
|
7
7
|
import { ValidationError } from "../../../shared/errors/index";
|
|
8
8
|
export async function reservePreOrderAction(input) {
|
|
9
9
|
return wrapAction(async () => {
|
|
10
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
10
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
11
11
|
const parsed = reservePreOrderSchema.safeParse(input);
|
|
12
12
|
if (!parsed.success)
|
|
13
13
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid reservation input");
|
|
@@ -9,7 +9,7 @@ import { ValidationError } from "../../../shared/errors/index";
|
|
|
9
9
|
const ERR_INVALID_COUPON_INPUT = "Invalid coupon input";
|
|
10
10
|
export async function applyCouponAction(input) {
|
|
11
11
|
return wrapAction(async () => {
|
|
12
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
12
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
13
13
|
const parsed = applyCouponSchema.safeParse(input);
|
|
14
14
|
if (!parsed.success)
|
|
15
15
|
throw new ValidationError(parsed.error.issues[0]?.message ?? ERR_INVALID_COUPON_INPUT);
|
|
@@ -8,7 +8,7 @@ import { createReviewSchema, replyToReviewSchema, deleteReviewSchema, } from "..
|
|
|
8
8
|
import { assertNotDuplicateReview, assertReviewOwnership, getReviewOrThrow, } from "./service";
|
|
9
9
|
export async function createReviewAction(input) {
|
|
10
10
|
return wrapAction(async () => {
|
|
11
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
11
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
12
12
|
const parsed = createReviewSchema.safeParse(input);
|
|
13
13
|
if (!parsed.success) {
|
|
14
14
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid input");
|
|
@@ -54,7 +54,7 @@ export async function replyToReviewAction(input) {
|
|
|
54
54
|
}
|
|
55
55
|
export async function deleteReviewAction(input) {
|
|
56
56
|
return wrapAction(async () => {
|
|
57
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
57
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
58
58
|
const parsed = deleteReviewSchema.safeParse(input);
|
|
59
59
|
if (!parsed.success) {
|
|
60
60
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid input");
|
|
@@ -71,7 +71,7 @@ export async function deleteReviewAction(input) {
|
|
|
71
71
|
}
|
|
72
72
|
export async function markReviewHelpfulAction(reviewId) {
|
|
73
73
|
return wrapAction(async () => {
|
|
74
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
74
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
75
75
|
await getReviewOrThrow(reviewId);
|
|
76
76
|
// Keyed on the voter so a repeated call is a no-op rather than another +1.
|
|
77
77
|
return reviewRepository.voteHelpful(reviewId, user.uid);
|
|
@@ -7,7 +7,7 @@ import { WISHLIST_MAX } from "../../../shared/features/wishlist/config";
|
|
|
7
7
|
import { WishlistCapError } from "../../../shared/features/wishlist/errors";
|
|
8
8
|
export async function addToWishlistAction(productId, extras) {
|
|
9
9
|
return wrapAction(async () => {
|
|
10
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
10
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
11
11
|
try {
|
|
12
12
|
return await wishlistRepository.addItem(user.uid, productId, extras);
|
|
13
13
|
}
|
|
@@ -21,13 +21,13 @@ export async function addToWishlistAction(productId, extras) {
|
|
|
21
21
|
}
|
|
22
22
|
export async function removeFromWishlistAction(productId) {
|
|
23
23
|
return wrapAction(async () => {
|
|
24
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
24
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
25
25
|
await wishlistRepository.removeItem(user.uid, productId);
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
export async function mergeGuestWishlistAction(guestItems) {
|
|
29
29
|
return wrapAction(async () => {
|
|
30
|
-
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
30
|
+
const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
|
|
31
31
|
const merged = [];
|
|
32
32
|
for (const item of guestItems) {
|
|
33
33
|
try {
|
|
@@ -141,9 +141,35 @@ export function AdminOrdersView({ children, ...props }) {
|
|
|
141
141
|
? `${title}${extraCount > 0 ? ` +${extraCount} more` : ""}`
|
|
142
142
|
: `Order ${orderId}`,
|
|
143
143
|
secondary: [
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
/*
|
|
145
|
+
* 🛑 `userName` and `totalPrice` FIRST — they are the document's
|
|
146
|
+
* real field names (OrderDocument, and the live response of
|
|
147
|
+
* GET /api/admin/orders).
|
|
148
|
+
*
|
|
149
|
+
* This read `buyerName ?? customerName` and
|
|
150
|
+
* `totalAmount ?? total ?? amount`: five names, not one of which
|
|
151
|
+
* the order document has ever carried. So every row rendered
|
|
152
|
+
* "Unknown buyer · -", on all 25 rows, for as long as the view has
|
|
153
|
+
* existed — and the `??` chains made it look like considered
|
|
154
|
+
* defensive coding rather than a guess. A fallback spelled three
|
|
155
|
+
* ways is the tell that nobody checked which one was real.
|
|
156
|
+
*
|
|
157
|
+
* The aliases are GONE rather than demoted to fallbacks: nothing
|
|
158
|
+
* declares them (the client `Order` type has no such fields) and
|
|
159
|
+
* nothing emits them (no adapter renames to them). Keeping a
|
|
160
|
+
* fallback with no producer only preserves the ambiguity that
|
|
161
|
+
* hid the bug.
|
|
162
|
+
*/
|
|
163
|
+
toStringValue(item.userName, "Unknown buyer"),
|
|
164
|
+
toCurrency(item.totalPrice),
|
|
165
|
+
/*
|
|
166
|
+
* Not `.slice(0, 14)` — that cut mid-date, so
|
|
167
|
+
* `order-1-20260822-aucwon` and `order-1-20260821-prizedr` both
|
|
168
|
+
* rendered as "order-1-202608". A truncation that destroys
|
|
169
|
+
* uniqueness is worse than a long string, because the id is the
|
|
170
|
+
* one thing on the row an admin searches by.
|
|
171
|
+
*/
|
|
172
|
+
orderId,
|
|
147
173
|
paymentReviewLabel(item),
|
|
148
174
|
]
|
|
149
175
|
.filter(Boolean)
|
|
@@ -366,13 +366,37 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
|
|
|
366
366
|
const loc = item.physicalLocation;
|
|
367
367
|
return {
|
|
368
368
|
id: toStringValue(item.id, `order-${index}`),
|
|
369
|
-
|
|
370
|
-
|
|
369
|
+
/*
|
|
370
|
+
* 🛑 The row says WHAT WAS SOLD, not the id repeated.
|
|
371
|
+
*
|
|
372
|
+
* This was `Order ${id.slice(0, 14)}` — a raw id, truncated
|
|
373
|
+
* mid-date, so two different orders rendered identically. The title
|
|
374
|
+
* was available the whole time: `items[0].productTitle` is
|
|
375
|
+
* denormalised onto every order precisely so a list never needs a
|
|
376
|
+
* second fetch (Root Cause #52), and it is already read three lines
|
|
377
|
+
* below as `itemTitle`.
|
|
378
|
+
*/
|
|
379
|
+
primary: (() => {
|
|
380
|
+
const title = typeof firstItem.productTitle === "string" ? firstItem.productTitle : "";
|
|
381
|
+
if (!title)
|
|
382
|
+
return `Order ${toStringValue(item.id, "-")}`;
|
|
383
|
+
const extra = itemsArr.length - 1;
|
|
384
|
+
return extra > 0 ? `${title} +${extra} more` : title;
|
|
385
|
+
})(),
|
|
386
|
+
/*
|
|
387
|
+
* `userName` / `totalPrice` are the document's real field names.
|
|
388
|
+
* `buyerName`/`buyerDisplayName`/`totalAmount`/`total` are four
|
|
389
|
+
* spellings the order document has never carried, so every seller's
|
|
390
|
+
* order list showed "Unknown buyer" and ₹0 — see AdminOrdersView for
|
|
391
|
+
* the full writeup. They are removed rather than demoted: nothing
|
|
392
|
+
* declares them and nothing emits them.
|
|
393
|
+
*/
|
|
394
|
+
secondary: toStringValue(item.userName, "Unknown buyer"),
|
|
371
395
|
status: toStringValue(item.status, "PENDING"),
|
|
372
396
|
updatedAt: toRelativeDate(item.updatedAt ?? item.orderDate ?? item.createdAt),
|
|
373
397
|
itemCount: itemsArr.length,
|
|
374
|
-
totalAmount: Number(item.
|
|
375
|
-
buyerName: toStringValue(item.
|
|
398
|
+
totalAmount: Number(item.totalPrice ?? 0),
|
|
399
|
+
buyerName: toStringValue(item.userName, "Unknown buyer"),
|
|
376
400
|
itemImage: typeof firstItem.image === "string" ? firstItem.image : undefined,
|
|
377
401
|
itemTitle: typeof firstItem.productTitle === "string" ? firstItem.productTitle : undefined,
|
|
378
402
|
physicalLocation: loc && typeof loc.zone === "string"
|
|
@@ -73,15 +73,29 @@ export const authored = {
|
|
|
73
73
|
roles: ["buyer"],
|
|
74
74
|
startPage: "/user/orders",
|
|
75
75
|
steps: [
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
/*
|
|
77
|
+
* 🛑 rehan, NOT vivaan — and the order changed with it.
|
|
78
|
+
*
|
|
79
|
+
* This said vivaan.kapoor@gmail.com (user-seto-kaiba), who does own
|
|
80
|
+
* order-1-20251107-11joon. But TWO other cases in this same batch use
|
|
81
|
+
* that order as a FOREIGN one, and a batch browses as exactly one
|
|
82
|
+
* identity — so the page could not be worked as authored: the same
|
|
83
|
+
* order had to be both owned and not-owned by the signed-in user.
|
|
84
|
+
*
|
|
85
|
+
* rehan.sheikh@gmail.com (user-yugi-muto) is the harness's `main`
|
|
86
|
+
* identity, and order-1-20260818-stdctx is one of its delivered orders.
|
|
87
|
+
* That makes the whole batch coherent under one session and leaves the
|
|
88
|
+
* access-control cases genuinely foreign.
|
|
89
|
+
*/
|
|
90
|
+
"Sign in as rehan.sheikh@gmail.com / TempPass123! — this persona owns the order below, and a return can only be requested on a delivered one.",
|
|
91
|
+
"Open /user/orders and open order-1-20260818-stdctx, which is delivered.",
|
|
78
92
|
"Use the Return action.",
|
|
79
93
|
"Give the reason: item not as described.",
|
|
80
94
|
"Submit the request.",
|
|
81
95
|
"Reload the order.",
|
|
82
96
|
"Open /user/returns and look for it.",
|
|
83
97
|
],
|
|
84
|
-
inputs: { orderId: "order-1-
|
|
98
|
+
inputs: { orderId: "order-1-20260818-stdctx", reason: "item not as described" },
|
|
85
99
|
expectedBehaviour: "A return request moves the order into Return Requested and appears on the returns surface. That status is deliberately an ACTIVE one — it is the seller's next action item, not a closed state — so the order must not disappear from the active list.",
|
|
86
100
|
expectedUiState: "The order's status reads Return Requested, and the same order is listed under /user/returns.",
|
|
87
101
|
expectedData: { statusAfterReturn: "return_requested" },
|
|
@@ -545,7 +545,25 @@ const acquisitionOrders = [
|
|
|
545
545
|
shippingCarrier: "Delhivery",
|
|
546
546
|
orderDate: daysAgo(12),
|
|
547
547
|
shippingDate: daysAgo(9),
|
|
548
|
-
|
|
548
|
+
/*
|
|
549
|
+
* 🛑 TWO DAYS, NOT SIX — THIS IS THE RETURN-WINDOW FIXTURE.
|
|
550
|
+
*
|
|
551
|
+
* A return can only be requested on a DELIVERED order inside the 7-day
|
|
552
|
+
* window, and you cannot reach "delivered" by buying in a test: it needs
|
|
553
|
+
* seller action. So the return flow is testable only if a seeded delivered
|
|
554
|
+
* order sits inside the window — and until now none did for the harness's
|
|
555
|
+
* own identity. Every candidate was 6, 7, 8, 20, 29 days old, so
|
|
556
|
+
* /user/orders/{id}/return answered 'The 7-day return window for this
|
|
557
|
+
* order has closed.' and the case could never be worked.
|
|
558
|
+
*
|
|
559
|
+
* Six days would have been inside the window today and OUTSIDE it
|
|
560
|
+
* tomorrow — a fixture that passes on Monday and fails on Tuesday is worse
|
|
561
|
+
* than one that always fails, because the failure looks like a regression.
|
|
562
|
+
* Two days leaves five days of margin.
|
|
563
|
+
*
|
|
564
|
+
* Do not raise this without checking RETURN_WINDOW_DAYS.
|
|
565
|
+
*/
|
|
566
|
+
deliveryDate: daysAgo(2),
|
|
549
567
|
createdAt: daysAgo(12),
|
|
550
568
|
updatedAt: daysAgo(6),
|
|
551
569
|
sourceContext: { path: "standard", listPrice: 999 },
|