@sayren/store-sdk 0.29.3 → 0.29.5
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/index.d.mts +177 -75
- package/dist/index.mjs +90 -19
- package/package.json +1 -1
- package/src/schemas/collection.ts +99 -7
- package/src/schemas/promotion.ts +27 -14
package/dist/index.mjs
CHANGED
|
@@ -1970,7 +1970,7 @@ const COLLECTION_SLUG_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
|
1970
1970
|
/** 유형 — `MANUAL`(직접 선택)·`AUTOMATIC`(조건 자동) */
|
|
1971
1971
|
const COLLECTION_TYPES = ["MANUAL", "AUTOMATIC"];
|
|
1972
1972
|
/**
|
|
1973
|
-
* 상품 정렬 — `MANUAL`은 직접 정한 순서(직접 선택 컬렉션만)다. `BEST_SELLING`(판매량순)은
|
|
1973
|
+
* 상품 정렬 — `MANUAL`은 직접 정한 순서(직접 선택 컬렉션만)다. `BEST_SELLING`(판매량순)은 판매 수량이 많은 순이다(M3).
|
|
1974
1974
|
* 저장 값 전체 목록이고, 쓰기에서 받는 값은 `collectionProductSortRequestSchema`다.
|
|
1975
1975
|
*/
|
|
1976
1976
|
const COLLECTION_PRODUCT_SORTS = [
|
|
@@ -1986,12 +1986,13 @@ const COLLECTION_PRODUCT_SORTS = [
|
|
|
1986
1986
|
const collectionProductSortRequestSchema = z.enum([
|
|
1987
1987
|
"MANUAL",
|
|
1988
1988
|
"LATEST",
|
|
1989
|
+
"BEST_SELLING",
|
|
1989
1990
|
"PRICE_ASC",
|
|
1990
1991
|
"PRICE_DESC",
|
|
1991
1992
|
"REVIEW_COUNT",
|
|
1992
1993
|
"RATING_DESC",
|
|
1993
1994
|
"RECOMMEND"
|
|
1994
|
-
]).describe("스토어프론트 상품 기본 정렬. `MANUAL`(직접 정한 순서)·`LATEST`(최신순)·`PRICE_ASC`·`PRICE_DESC`·`REVIEW_COUNT`·`RATING_DESC`·`RECOMMEND`(추천순)");
|
|
1995
|
+
]).describe("스토어프론트 상품 기본 정렬. `MANUAL`(직접 정한 순서)·`LATEST`(최신순)·`BEST_SELLING`(판매량순)·`PRICE_ASC`·`PRICE_DESC`·`REVIEW_COUNT`·`RATING_DESC`·`RECOMMEND`(추천순). 판매량순의 기간은 판매량 상위 조건의 기간이고, 조건이 없으면 최근 30일이다");
|
|
1995
1996
|
/** 노출 상태 — 노출 여부와 기간에서 나온 값이다. 숨김이 기간보다 앞선다 */
|
|
1996
1997
|
const collectionStateSchema = z.enum([
|
|
1997
1998
|
"ACTIVE",
|
|
@@ -2015,6 +2016,16 @@ const MAX_COLLECTION_RULE_CATEGORIES = 20;
|
|
|
2015
2016
|
const MAX_COLLECTION_CREATED_WITHIN_DAYS = 365;
|
|
2016
2017
|
/** 미리보기(`POST /v1/collections/preview`)가 싣는 상품 최대 개수 */
|
|
2017
2018
|
const COLLECTION_PREVIEW_SIZE = 20;
|
|
2019
|
+
/** 판매량 상위 조건의 기간 선택지(일, 오늘 포함 한국 날짜) */
|
|
2020
|
+
const COLLECTION_BEST_SELLING_DAYS = [
|
|
2021
|
+
7,
|
|
2022
|
+
30,
|
|
2023
|
+
90
|
|
2024
|
+
];
|
|
2025
|
+
/** 판매량 상위 조건이 담는 상품 최대 개수 */
|
|
2026
|
+
const MAX_COLLECTION_BEST_SELLING_TOP = 100;
|
|
2027
|
+
/** 판매량순(`BEST_SELLING`) 정렬의 기간 — 판매량 상위 조건이 없을 때 쓴다 */
|
|
2028
|
+
const COLLECTION_SALES_SORT_DEFAULT_DAYS = 30;
|
|
2018
2029
|
const createdWithinDaysRuleSchema = z.object({
|
|
2019
2030
|
field: z.literal("createdWithinDays"),
|
|
2020
2031
|
value: z.number().int().min(1).max(365).describe("등록한 지 N일 안의 상품(1~365). 조회 시각에서 N일을 뺀 시각 이후에 등록한 상품이다")
|
|
@@ -2032,15 +2043,26 @@ const discountedRuleSchema = z.object({
|
|
|
2032
2043
|
field: z.literal("discounted"),
|
|
2033
2044
|
value: z.literal(true).describe("즉시할인이 지금 적용되는 상품")
|
|
2034
2045
|
});
|
|
2046
|
+
const bestSellingRuleSchema = z.object({
|
|
2047
|
+
field: z.literal("bestSelling"),
|
|
2048
|
+
days: z.union([
|
|
2049
|
+
z.literal(7),
|
|
2050
|
+
z.literal(30),
|
|
2051
|
+
z.literal(90)
|
|
2052
|
+
]).describe("판매량을 세는 기간(일). 7·30·90 중 하나이고 오늘을 포함한 한국 날짜 기준이다"),
|
|
2053
|
+
top: z.number().int().min(1).max(100).describe("담을 상품 수(1~100). 다른 조건을 만족하는 상품 중 판매 수량 상위 N개다")
|
|
2054
|
+
});
|
|
2035
2055
|
/**
|
|
2036
2056
|
* 조건 하나 — `field`로 가른다. 가격은 즉시할인을 반영한 판매가(`discountedPrice ?? salePrice`)다.
|
|
2037
|
-
* 판매량 상위(`bestSelling`)는
|
|
2057
|
+
* 판매량 상위(`bestSelling`)는 술어가 아니라 순위 자르기다. 다른 조건을 모두 만족한 상품 중 판매 수량 상위 N개만 남긴다(`rankBestSelling`).
|
|
2058
|
+
* 판매 수량은 실결제 주문의 결제 수량에서 취소·반품 수량을 뺀 값이고, 날짜는 주문 시각의 한국 날짜다. 집계는 최대 10분 늦다.
|
|
2038
2059
|
*/
|
|
2039
2060
|
const collectionRuleSchema = z.discriminatedUnion("field", [
|
|
2040
2061
|
createdWithinDaysRuleSchema,
|
|
2041
2062
|
categoryRuleSchema,
|
|
2042
2063
|
priceRuleSchema,
|
|
2043
|
-
discountedRuleSchema
|
|
2064
|
+
discountedRuleSchema,
|
|
2065
|
+
bestSellingRuleSchema
|
|
2044
2066
|
]).superRefine((rule, ctx) => {
|
|
2045
2067
|
if (rule.field !== "price") return;
|
|
2046
2068
|
if (rule.min === void 0 && rule.max === void 0) ctx.addIssue({
|
|
@@ -2074,6 +2096,7 @@ const collectionRuleViewSchema = z.union([
|
|
|
2074
2096
|
categoryRuleSchema,
|
|
2075
2097
|
priceRuleSchema,
|
|
2076
2098
|
discountedRuleSchema,
|
|
2099
|
+
bestSellingRuleSchema,
|
|
2077
2100
|
z.looseObject({ field: z.string() })
|
|
2078
2101
|
]);
|
|
2079
2102
|
const DAY_MS = 864e5;
|
|
@@ -2098,6 +2121,7 @@ function descendantCategoryIdsOf(roots, categories) {
|
|
|
2098
2121
|
/**
|
|
2099
2122
|
* 조건 판정 함수를 만든다 — 모든 조건을 만족해야 true다(AND). 카테고리 트리는 여기서 한 번만 푼다.
|
|
2100
2123
|
* 알 수 없는 조건(`field`)은 만족하지 않는 것으로 본다. 모르는 조건을 건너뛰면 상품이 예고 없이 늘어난다.
|
|
2124
|
+
* 판매량 상위(`bestSelling`)는 여기서 모두 통과시킨다. 순위 자르기는 판매량을 아는 호출부가 `rankBestSelling`으로 한다.
|
|
2101
2125
|
* 판매 상태는 보지 않는다. 판매 중만 거르는 것은 호출부다.
|
|
2102
2126
|
*/
|
|
2103
2127
|
function collectionRulesPredicate(rules, context) {
|
|
@@ -2119,6 +2143,7 @@ function collectionRulesPredicate(rules, context) {
|
|
|
2119
2143
|
return (parsed.min === void 0 || price >= parsed.min) && (parsed.max === void 0 || price <= parsed.max);
|
|
2120
2144
|
};
|
|
2121
2145
|
case "discounted": return (product) => product.discountedPrice !== null && product.discountedPrice < product.salePrice;
|
|
2146
|
+
case "bestSelling": return () => true;
|
|
2122
2147
|
default: return () => false;
|
|
2123
2148
|
}
|
|
2124
2149
|
});
|
|
@@ -2128,6 +2153,31 @@ function collectionRulesPredicate(rules, context) {
|
|
|
2128
2153
|
function matchesCollectionRules(product, rules, context) {
|
|
2129
2154
|
return collectionRulesPredicate(rules, context)(product);
|
|
2130
2155
|
}
|
|
2156
|
+
/** 판매량 상위 조건 — 없으면 null. 같은 조건은 한 번만 쓰므로 첫 번째다 */
|
|
2157
|
+
function bestSellingRuleOf(rules) {
|
|
2158
|
+
for (const rule of rules) {
|
|
2159
|
+
const parsed = bestSellingRuleSchema.safeParse(rule);
|
|
2160
|
+
if (parsed.success) return {
|
|
2161
|
+
days: parsed.data.days,
|
|
2162
|
+
top: parsed.data.top
|
|
2163
|
+
};
|
|
2164
|
+
}
|
|
2165
|
+
return null;
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* 판매량 비교 — 판매 수량이 많은 순, 같으면 최근 등록 순, 그것도 같으면 상품 id 순이다. 결과가 입력 순서에 기대지 않는다.
|
|
2169
|
+
* `sales`에 없는 상품은 0개다.
|
|
2170
|
+
*/
|
|
2171
|
+
function compareBySales(sales) {
|
|
2172
|
+
return (a, b) => (sales.get(b.productId) ?? 0) - (sales.get(a.productId) ?? 0) || Date.parse(b.createdAt) - Date.parse(a.createdAt) || (a.productId < b.productId ? -1 : a.productId > b.productId ? 1 : 0);
|
|
2173
|
+
}
|
|
2174
|
+
/**
|
|
2175
|
+
* 판매량 상위 자르기 — 다른 조건을 통과한 상품 중 판매 수량이 1개 이상인 상품을 `compareBySales` 순으로 `top`개 남긴다.
|
|
2176
|
+
* 판매가 없는 상품은 넣지 않는다.
|
|
2177
|
+
*/
|
|
2178
|
+
function rankBestSelling(products, sales, top) {
|
|
2179
|
+
return products.filter((product) => (sales.get(product.productId) ?? 0) > 0).sort(compareBySales(sales)).slice(0, Math.max(0, top));
|
|
2180
|
+
}
|
|
2131
2181
|
/** 조건이 참조하는 카테고리 id — 카테고리 삭제의 참조 검사에 쓴다 */
|
|
2132
2182
|
function collectionRuleCategoryIds(rules) {
|
|
2133
2183
|
const ids = [];
|
|
@@ -2153,6 +2203,7 @@ const collectionSchema = z.object({
|
|
|
2153
2203
|
metaTitle: z.string().nullable(),
|
|
2154
2204
|
metaDescription: z.string().nullable(),
|
|
2155
2205
|
state: collectionStateSchema.describe("지금 노출 상태"),
|
|
2206
|
+
salesComputedAt: z.string().nullable().default(null).describe("판매량 기준 시각. 판매량 상위 조건이나 판매량순 정렬을 쓰는 컬렉션은 이 시각까지의 주문을 센다(최대 10분 늦다). 판매량을 쓰지 않거나 아직 집계 전이면 null"),
|
|
2156
2207
|
productCount: z.number().int().describe("상품 수. 직접 선택은 담긴 상품 수(판매 상태 무관), 조건 자동은 지금 조건을 만족하는 판매 중 상품 수"),
|
|
2157
2208
|
revision: z.number().int().describe("수정 번호. 쓰기마다 1씩 오른다. 수정 본문에 주면 그 사이 다른 수정이 있을 때 409다"),
|
|
2158
2209
|
createdAt: z.string(),
|
|
@@ -2182,7 +2233,7 @@ const periodRefine = (body, ctx) => {
|
|
|
2182
2233
|
/**
|
|
2183
2234
|
* `POST /v1/collections` — 컬렉션을 만든다. `slug`를 생략하면 `c-{id 뒤 8자}`로 만든다.
|
|
2184
2235
|
* 직접 선택(`MANUAL`)은 `productIds`가 처음 담을 상품과 순서다. 조건 자동(`AUTOMATIC`)은 `rules`가 있어야 하고 `productIds`를 받지 않는다.
|
|
2185
|
-
* `productSort`를 생략하면 직접 선택은 `MANUAL`, 조건 자동은 `LATEST
|
|
2236
|
+
* `productSort`를 생략하면 직접 선택은 `MANUAL`, 조건 자동은 `LATEST`(판매량 상위 조건이 있으면 `BEST_SELLING`)다. 조건 자동은 `MANUAL`을 쓸 수 없다.
|
|
2186
2237
|
*/
|
|
2187
2238
|
const collectionCreateRequestSchema = z.object({
|
|
2188
2239
|
title: z.string().trim().min(1).max(60).describe("제목"),
|
|
@@ -2191,7 +2242,7 @@ const collectionCreateRequestSchema = z.object({
|
|
|
2191
2242
|
rules: collectionRulesSchema.optional().describe("조건 자동 컬렉션의 조건(AND). 조건 자동이면 필수, 직접 선택이면 줄 수 없다"),
|
|
2192
2243
|
description: commonFields.description.default(""),
|
|
2193
2244
|
imageUrl: commonFields.imageUrl.optional(),
|
|
2194
|
-
productSort: commonFields.productSort.optional().describe("스토어프론트 상품 기본 정렬. 생략하면 직접 선택은 `MANUAL`, 조건 자동은 `LATEST
|
|
2245
|
+
productSort: commonFields.productSort.optional().describe("스토어프론트 상품 기본 정렬. 생략하면 직접 선택은 `MANUAL`, 조건 자동은 `LATEST`(판매량 상위 조건이 있으면 `BEST_SELLING`)다. 조건 자동은 `MANUAL`을 쓸 수 없다"),
|
|
2195
2246
|
visible: commonFields.visible.default(true),
|
|
2196
2247
|
startsAt: commonFields.startsAt,
|
|
2197
2248
|
endsAt: commonFields.endsAt,
|
|
@@ -2265,12 +2316,13 @@ const collectionProductListQuerySchema = z.object({ ...pageQueryShape({
|
|
|
2265
2316
|
/** `POST /v1/collections/preview` — 저장하지 않고 조건으로 나오는 상품을 본다 */
|
|
2266
2317
|
const collectionPreviewRequestSchema = z.object({
|
|
2267
2318
|
rules: collectionRulesSchema,
|
|
2268
|
-
productSort: collectionProductSortRequestSchema.optional().describe("미리보기 순서.
|
|
2319
|
+
productSort: collectionProductSortRequestSchema.optional().describe("미리보기 순서. 생략하면 `LATEST`(판매량 상위 조건이 있으면 `BEST_SELLING`)이고, `MANUAL`이면 `LATEST`다")
|
|
2269
2320
|
});
|
|
2270
2321
|
/** 미리보기 응답 — 조건을 만족하는 판매 중 상품 수와 앞 20개 */
|
|
2271
2322
|
const collectionPreviewSchema = z.object({
|
|
2272
2323
|
count: z.number().int().describe("조건을 만족하는 판매 중 상품 수(조회 시각 기준)"),
|
|
2273
|
-
products: z.array(collectionProductSchema).describe("앞 20개(정렬 순)")
|
|
2324
|
+
products: z.array(collectionProductSchema).describe("앞 20개(정렬 순)"),
|
|
2325
|
+
salesComputedAt: z.string().nullable().default(null).describe("판매량 기준 시각. 판매량 상위 조건이나 판매량순 정렬을 쓰면 이 시각까지의 주문을 센다. 판매량을 쓰지 않거나 집계 전이면 null")
|
|
2274
2326
|
});
|
|
2275
2327
|
//#endregion
|
|
2276
2328
|
//#region src/schemas/promotion.ts
|
|
@@ -2678,8 +2730,10 @@ function quotePricing(input) {
|
|
|
2678
2730
|
};
|
|
2679
2731
|
}
|
|
2680
2732
|
/**
|
|
2681
|
-
* 사용 적립금 금액(순수) — 요청·잔액·최대
|
|
2682
|
-
*
|
|
2733
|
+
* 사용 적립금 금액(순수) — 요청·잔액·최대 비율 중 작은 값을 쓴다(#93 P3·P4).
|
|
2734
|
+
* - 결제 금액 전체를 덮을 수 있으면 전액을 쓴다(0원 결제, 이때만 사용 단위를 보지 않는다)
|
|
2735
|
+
* - 그 밖에는 사용 단위로 내리고, 남는 결제 금액이 1~99원이면 적립금을 줄여 100원을 남긴다(`MIN_PAYMENT`)
|
|
2736
|
+
* 최소 보유액·최소 사용액에 못 미치면 0이다.
|
|
2683
2737
|
*/
|
|
2684
2738
|
function pointUseOf(points, amounts) {
|
|
2685
2739
|
const none = {
|
|
@@ -2693,12 +2747,29 @@ function pointUseOf(points, amounts) {
|
|
|
2693
2747
|
const unit = Math.max(1, Math.floor(rules.unit));
|
|
2694
2748
|
const base = amounts.productPaid + (rules.includeDeliveryFee ? amounts.deliveryPaid : 0);
|
|
2695
2749
|
const byRatio = Math.floor(base * rules.maxRatioBp / 1e4);
|
|
2696
|
-
const byPayment = Math.max(0, amounts.total - 100);
|
|
2697
2750
|
const balance = Math.max(0, points.balance);
|
|
2751
|
+
const total = Math.max(0, amounts.total);
|
|
2698
2752
|
const floorUnit = (value) => Math.floor(Math.max(0, value) / unit) * unit;
|
|
2753
|
+
/** 상한 `cap`으로 쓸 수 있는 금액 — 전액이면 0원 결제, 아니면 단위 내림 + 100원 남기기 */
|
|
2754
|
+
const usableWithin = (cap) => {
|
|
2755
|
+
if (total > 0 && cap >= total) return {
|
|
2756
|
+
amount: total,
|
|
2757
|
+
adjusted: false
|
|
2758
|
+
};
|
|
2759
|
+
const amount = floorUnit(Math.min(cap, total));
|
|
2760
|
+
const remaining = total - amount;
|
|
2761
|
+
if (remaining > 0 && remaining < 100) return {
|
|
2762
|
+
amount: floorUnit(total - 100),
|
|
2763
|
+
adjusted: true
|
|
2764
|
+
};
|
|
2765
|
+
return {
|
|
2766
|
+
amount,
|
|
2767
|
+
adjusted: false
|
|
2768
|
+
};
|
|
2769
|
+
};
|
|
2699
2770
|
const eligible = balance >= rules.minBalance;
|
|
2700
|
-
const ceiling = Math.min(balance, byRatio
|
|
2701
|
-
const maxUsable = eligible &&
|
|
2771
|
+
const ceiling = usableWithin(Math.min(balance, byRatio)).amount;
|
|
2772
|
+
const maxUsable = eligible && ceiling > 0 && ceiling >= rules.minAmount ? ceiling : 0;
|
|
2702
2773
|
const requested = Math.max(0, Math.floor(points.requested));
|
|
2703
2774
|
if (requested === 0) return {
|
|
2704
2775
|
...none,
|
|
@@ -2710,23 +2781,23 @@ function pointUseOf(points, amounts) {
|
|
|
2710
2781
|
adjustReason: null,
|
|
2711
2782
|
rejectReason: "MIN_BALANCE"
|
|
2712
2783
|
};
|
|
2713
|
-
const
|
|
2714
|
-
if (amount <= 0) return {
|
|
2784
|
+
const used = usableWithin(Math.min(requested, balance, byRatio));
|
|
2785
|
+
if (used.amount <= 0) return {
|
|
2715
2786
|
amount: 0,
|
|
2716
2787
|
maxUsable,
|
|
2717
2788
|
adjustReason: null,
|
|
2718
2789
|
rejectReason: "NOT_PAYABLE"
|
|
2719
2790
|
};
|
|
2720
|
-
if (amount < rules.minAmount) return {
|
|
2791
|
+
if (used.amount < rules.minAmount) return {
|
|
2721
2792
|
amount: 0,
|
|
2722
2793
|
maxUsable,
|
|
2723
2794
|
adjustReason: null,
|
|
2724
2795
|
rejectReason: "MIN_AMOUNT"
|
|
2725
2796
|
};
|
|
2726
2797
|
return {
|
|
2727
|
-
amount,
|
|
2798
|
+
amount: used.amount,
|
|
2728
2799
|
maxUsable,
|
|
2729
|
-
adjustReason:
|
|
2800
|
+
adjustReason: used.adjusted ? "MIN_PAYMENT" : null,
|
|
2730
2801
|
rejectReason: null
|
|
2731
2802
|
};
|
|
2732
2803
|
}
|
|
@@ -7378,4 +7449,4 @@ function createStoreSession(options) {
|
|
|
7378
7449
|
};
|
|
7379
7450
|
}
|
|
7380
7451
|
//#endregion
|
|
7381
|
-
export { APPROVAL_ALREADY_DECIDED_CODE, APPROVAL_REQUIRED_CODE, ApiError, ApprovalPendingError, BUSINESS_INFO_MAX_LENGTH, BUSINESS_NUMBER_PATTERN, CASH_RECEIPT_STATUS_VALUES, COLLECTION_PREVIEW_SIZE, COLLECTION_PRODUCT_SORTS, COLLECTION_SLUG_PATTERN, COLLECTION_TYPES, COUPON_CODE_PATTERN, COUPON_CONDITIONS_DEFAULTS, COUPON_TARGET_ALL, COUPON_TARGET_LIST_MAX, CUSTOM_INPUT_FORBIDDEN_WORDS, FULFILLMENT_RULES, MAX_ADDON_GROUPS, MAX_ANALYTICS_ALLOWED_ORIGINS, MAX_AUTO_TRANSITION_DAYS, MAX_COLLECTIONS, MAX_COLLECTION_CREATED_WITHIN_DAYS, MAX_COLLECTION_DESCRIPTION, MAX_COLLECTION_PRODUCTS, MAX_COLLECTION_PRODUCTS_PER_ADD, MAX_COLLECTION_RULES, MAX_COLLECTION_RULE_CATEGORIES, MAX_COLLECTION_TITLE, MAX_CUSTOM_INPUTS, MAX_CUSTOM_INPUT_LENGTH, MAX_OPTION_GROUPS, MAX_PRODUCT_IMAGES, MAX_SAVED_OPTION_SETS, MAX_SAVED_OPTION_SET_NAME, MAX_VALUES_PER_GROUP, MAX_VARIANTS, MCP_TELEMETRY_MAX_RESULTS, MIN_PAYMENT_AMOUNT, NO_COUPON_SETTLEMENT, NO_SHIPPING_BUNDLE_KEY, PAYMENT_ROUTING_EXCLUSION_CODES, POINT_ADJUSTMENT_MAX, POINT_EARN_RATE_BP_MAX, POINT_ENTRY_TYPES, POINT_EXPIRY_DAYS_MAX, POINT_EXPIRY_DAYS_MIN, POINT_LOT_SOURCES, POINT_POLICY_DEFAULTS, POINT_REVIEW_REWARD_MAX, POINT_USE_UNITS, PORTONE_CHANNEL_NAME_MAX_LENGTH, PORTONE_MAX_CHANNELS, PORTONE_MIN_CHANNELS, REFUND_POLICY_DEFAULTS, REFUND_POLICY_DELIVERY_FEE_KEYS, REMOTE_AREA_ZIP_RANGES, RESERVED_STOREFRONT_SLUGS, RESERVED_STORE_CODES, SHIPPING_POLICY_DEFAULTS, STOREFRONT_BLOCKED_PATH_SEGMENTS, STOREFRONT_BUILD_STAGES, STOREFRONT_BUILD_TERMINAL_STATUSES, STOREFRONT_CHECK_TERMINAL_STATUSES, STOREFRONT_CUSTOM_DOMAIN_LIMIT_DEFAULT, STOREFRONT_DOMAIN_DNS_GRACE_DAYS, STOREFRONT_DOMAIN_DNS_WAIT_DAYS, STOREFRONT_DOMAIN_TXT_LABEL, STOREFRONT_EDIT_ACTIVITY_TIMEOUT_MINUTES, STOREFRONT_EDIT_CAPACITY, STOREFRONT_EDIT_IDLE_MINUTES, STOREFRONT_EDIT_PREVIEW_SUFFIX, STOREFRONT_EDIT_START_STAGES, STOREFRONT_FILE_BATCH_MAX, STOREFRONT_FILE_MAX_BYTES, STOREFRONT_PATH_SEGMENT_PATTERN, STOREFRONT_PLATFORM_DOMAINS, STOREFRONT_PUBLIC_SUFFIXES, STOREFRONT_SEARCH_REGEX_MAX_LENGTH, STOREFRONT_SHOWCASE_SLUG_PREFIX, STOREFRONT_SITE_CREATE_LIMIT, STOREFRONT_SLUG_CHANGE_LIMIT, STOREFRONT_SLUG_CHANGE_WINDOW_DAYS, STOREFRONT_SLUG_HOLD_DAYS, STOREFRONT_SLUG_PATTERN, STOREFRONT_SOURCE_BLOB_BATCH_MAX, STOREFRONT_SOURCE_PART_BYTES, STOREFRONT_WORKSPACE_MAX_BYTES, STOREFRONT_WORKSPACE_MAX_FILES, STORE_CODE_PATTERN, STORE_ROLE_SCOPES, STORE_SCOPE_RESOURCES, STORE_SESSION_KEYS, TOSS_WIDGET_CLIENT_KEY_PATTERN, TOSS_WIDGET_KEY_MESSAGE, TOSS_WIDGET_SECRET_KEY_PATTERN, UPLOAD_PURPOSE_LIMITS, VARIANT_COUNT_WARNING, VARIANT_STOCK_EXCLUSIVE_MESSAGE, WEBHOOK_DEFAULT_TOLERANCE_SEC, WEBHOOK_DELIVERY_ID_HEADER, WEBHOOK_EVENT_ID_HEADER, WEBHOOK_EVENT_TYPE_HEADER, WEBHOOK_FAILURE_REASONS, WEBHOOK_HEADERS, WEBHOOK_PAYLOAD_EXCERPT_MAX_BYTES, WEBHOOK_RESOURCE_TYPES, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_USER_AGENT, addStorefrontDomainRequestSchema, addonGroupRequestSchema, addonGroupSchema, addonValueRequestSchema, addonValueSchema, addressChangeRequestListSchema, addressTypeSchema, agentPolicyDecisionSchema, allocateByWeight, analyticsChannelSchema, analyticsCheckoutOutcomeSchema, analyticsCheckoutSchema, analyticsDeviceRowSchema, analyticsDevicesSchema, analyticsFunnelStepSchema, analyticsOriginSchema, analyticsOverviewSchema, analyticsPagesQuerySchema, analyticsPagesSchema, analyticsProductRowSchema, analyticsProductSortSchema, analyticsProductsQuerySchema, analyticsProductsSchema, analyticsRangeQuerySchema, analyticsRealtimeSchema, analyticsSearchQuerySchema, analyticsSearchSchema, analyticsSourceGroupBySchema, analyticsSourceRowSchema, analyticsSourcesQuerySchema, analyticsSourcesSchema, analyticsTotalsSchema, apiLogErrorSchema, apiLogListQuerySchema, apiLogPageSchema, apiLogPrincipalSchema, apiLogPrincipalTypeSchema, apiLogSchema, apiLogStatusFilterSchema, apiLogSummarySchema, approvalDecisionRequestSchema, approvalListQuerySchema, approvalPageSchema, approvalRequestSchema, approvalStatusSchema, approveClaimResultSchema, auditActorSchema, auditActorTypeSchema, auditLogListQuerySchema, auditLogOutcomeSchema, auditLogPageSchema, auditLogSchema, auditLogSourceSchema, buildAuthorizeUrl, buildQuery, bulkResultSchema, businessInfoPatchShape, businessInfoResponseShape, businessNumberSchema, cancelBySellerRequestSchema, cancelBySellerResultSchema, carrierSchema, cashReceiptSchema, categoryAttributeSchema, categoryCreateRequestSchema, categoryDeleteQuerySchema, categoryDeleteStrategySchema, categoryListQuerySchema, categoryPatchRequestSchema, categoryProductSortSchema, categorySchema, categorySearchResultSchema, categoryTreeNodeSchema, categoryWithPathSchema, changeStorefrontSlugRequestSchema, changeStorefrontTemplateRequestSchema, changeTypeSchema, claimDetailSchema, claimHoldResultSchema, claimListQuerySchema, claimReasonSchema, claimReturnAddressSchema, claimSchema, claimStatusSchema, claimTypeSchema, claimWebhookEventDataSchema, claimWebhookEventSchema, collectionCreateRequestSchema, collectionListQuerySchema, collectionPageSchema, collectionPatchRequestSchema, collectionPreviewRequestSchema, collectionPreviewSchema, collectionProductListQuerySchema, collectionProductSchema, collectionProductSortRequestSchema, collectionProductsAddRequestSchema, collectionProductsReplaceRequestSchema, collectionRuleCategoryIds, collectionRuleSchema, collectionRuleViewSchema, collectionRulesPredicate, collectionRulesSchema, collectionSchema, collectionStateCountsSchema, collectionStateOf, collectionStateSchema, consentActionSchema, consentKindSchema, consentSourceSchema, couponBenefitSchema, couponConditionsInputSchema, couponConditionsSchema, couponDiscountOf, couponIssueListQuerySchema, couponIssueMethodSchema, couponIssueSchema, couponIssueStatusSchema, couponKindSchema, couponListQuerySchema, couponRedemptionListQuerySchema, couponRedemptionSchema, couponRejectReasonSchema, couponRuleSchema, couponSchema, couponStatsSchema, couponStatusSchema, couponTargetInputSchema, couponTargetSchema, createCouponRequestSchema, createPkcePair, createStoreClient, createStoreSession, createStorefrontEditPreviewLinkRequestSchema, createStorefrontPreviewLinkRequestSchema, createStorefrontSiteRequestSchema, createStorefrontVersionRequestSchema, customInputLabelForbiddenWord, customInputRequestSchema, customInputSchema, customInputValueSchema, customerAddressSchema, customerConsentListQuerySchema, customerConsentSchema, customerConsentStateSchema, customerConsentsSchema, customerCouponSchema, customerDelegationRequestSchema, customerDelegationSchema, customerDetailSchema, customerInquiryCategorySchema, customerInquiryListQuerySchema, customerListQuerySchema, customerOrderSchema, customerPointsSchema, customerSortSchema, customerStatsSchema, customerSummarySchema, customerWithdrawalBlockedDetailsSchema, deleteStorefrontFileRequestSchema, deliveryBundleKeyOf, deliveryFeeWaiverSchema, deliveryInfoSchema, deliveryMethodSchema, deliveryStatusSchema, deliveryTypeSchema, descendantCategoryIdsOf, disableStorefrontHostingRequestSchema, discountRequestSchema, discountSchema, dispatchRequestSchema, easyPayProviderResponseSchema, easyPayProviderSchema, eventTypeSchema, exchangeAuthorizationCode, fulfillBulkRequestSchema, fulfillRequestSchema, fulfillmentRuleOf, fulfillmentTypeOf, fulfillmentTypeResponseSchema, fulfillmentTypeSchema, holdOrderItemRequestSchema, inquiryListQuerySchema, inquirySchema, inquiryWebhookEventDataSchema, inquiryWebhookEventSchema, invitationDeliveryStatusSchema, invitationListQuerySchema, invitationSchema, inviteMemberRequestSchema, isCouponTargetLine, isEditableStorefrontPath, isReservedStoreCode, isReservedStorefrontSlug, isShowcaseStorefrontSlug, isStoreScope, isWebOrigin, issueCouponRequestSchema, issueCouponResultSchema, liveGateConditionCodeSchema, liveGateConditionSchema, liveGateErrorDetailsSchema, liveGateSchema, loginProviderSchema, loginProviderStatusSchema, loginProviderTestSchema, loginSettingsSchema, maskedSecretSchema, matchesCollectionRules, mcpRuleResultSchema, mcpToolEventSchema, moveStorefrontFileRequestSchema, myAccountSchema, myStoreSchema, normalizeBusinessNumber, normalizeCouponCode, normalizeStorefrontHostname, normalizeStorefrontPath, oauthTokenResponseSchema, openFulfillmentUnion, optionGroupKindSchema, optionGroupRequestSchema, optionGroupSchema, optionModelRequestSchema, optionModelSchema, optionSelectionSchema, optionSortSchema, optionValueRequestSchema, optionValueSchema, orderCanceledWebhookEventDataSchema, orderCanceledWebhookEventSchema, orderDiscountSchema, orderFulfilledWebhookEventDataSchema, orderFulfilledWebhookEventSchema, orderItemFulfillmentSchema, orderItemFulfillmentSnapshotResponseSchema, orderItemFulfillmentSnapshotSchema, orderItemListQuerySchema, orderItemMemoResultSchema, orderItemPageSchema, orderItemSchema, orderItemStatusSchema, orderListQuerySchema, orderSchema, orderSummaryPageSchema, orderSummarySchema, orderWebhookEventDataSchema, orderWebhookEventSchema, pageInfoSchema, pageQueryShape, pageSchema, paymentAttemptRecordSchema, paymentAttemptStatusSchema, paymentCredentialSetSchema, paymentFailureWarningSchema, paymentListQuerySchema, paymentProviderSchema, paymentProviderVerificationSchema, paymentRecordDetailSchema, paymentRecordPageSchema, paymentRecordSchema, paymentRecordStatusSchema, paymentRefundRecordSchema, paymentSettingsSchema, pgEnvironmentSchema, pgPaymentMethodSchema, pgProviderSchema, pgVerificationResultSchema, planCodeSchema, planEntitlementsSchema, planErrorDetailsSchema, pointAdjustmentRequestSchema, pointAdjustmentResultSchema, pointEarnOf, pointEarnRateBpSchema, pointEarningEnabled, pointEntrySchema, pointExpiresAtOf, pointHistoryQuerySchema, pointLotSchema, pointPolicyNoticeSchema, pointPolicySchema, pointRestoreExpiresAtOf, pointUseOf, pointUsePolicySchema, policyDocumentUrlSchema, policyVersionSchema, portOneChannelSchema, portOneCredentialsInputSchema, productCreateRequestSchema, productFulfillmentCreateSchema, productFulfillmentResponseSchema, productFulfillmentSchema, productFulfillmentUpdateSchema, productImageRejection, productImageUrlSchema, productListQuerySchema, productOutOfStockWebhookEventDataSchema, productOutOfStockWebhookEventSchema, productPatchRequestSchema, productRefundPolicyOverride, productRefundPolicyPatchSchema, productReplaceRequestSchema, productSchema, productSortSchema, productStatusSchema, productSummarySchema, productVariantRequestSchema, productVariantSchema, proratedPaidRefundBase, proratedPointRefund, proratedRefundBase, publicPlanSchema, publicPlansSchema, publishStorefrontVersionRequestSchema, purchaseDecisionExtendResultSchema, purchaseDecisionRequestResultSchema, purchaseEarnPolicySchema, purchaseEarnRateOf, quoteDelivery, quotePricing, refreshUserToken, refundPolicyPatchSchema, refundPolicySchema, rejectClaimRequestSchema, remoteAreaLabelOf, remoteAreaOf, remoteAreaSchema, remoteSurchargeOf, replaceStorefrontSourceRequestSchema, requiresCollection, requiresShipping, resolvePointPolicy, resolveRefundPolicy, resolveShippingPolicy, responsePlanCodeSchema, responsePointEntryTypeSchema, reviewListQuerySchema, reviewReportResultSchema, reviewRewardPointOf, reviewRewardPolicySchema, reviewSchema, reviewSortSchema, reviewWebhookEventDataSchema, reviewWebhookEventSchema, rollbackStorefrontRequestSchema, runStorefrontCheckRequestSchema, salesReportGroupBySchema, salesReportQuerySchema, salesReportRowSchema, salesReportSchema, salesTotalsSchema, saveLoginProviderRequestSchema, savedCustomInputRequestSchema, savedCustomInputSchema, savedOptionGroupRequestSchema, savedOptionGroupSchema, savedOptionSetCompositionSchema, savedOptionSetFromProductRequestSchema, savedOptionSetFromProductResultSchema, savedOptionSetListQuerySchema, savedOptionSetRequestSchema, savedOptionSetSchema, savedOptionSetSortSchema, savedOptionValueRequestSchema, savedOptionValueSchema, scopeAccessSchema, searchStorefrontFilesRequestSchema, sellerAddressListQuerySchema, sellerAddressRequestSchema, sellerAddressSchema, sellerCustomerInquirySchema, setStorefrontVisibilityRequestSchema, settleCouponShortfall, settlementDetailQuerySchema, settlementDetailSchema, settlementListQuerySchema, settlementStatusSchema, settlementSummarySchema, settlementWithDetailsSchema, shippingAddressSchema, shippingPolicyPatchSchema, shippingPolicySchema, splitRefund, storeCodeSchema, storeMemberRoleUpdatedSchema, storeMemberSchema, storePointPolicySchema, storeRoleSchema, storeSchema, storeScopeResourceSchema, storeSubscriptionSchema, storefrontBuildDependenciesSchema, storefrontBuildListQuerySchema, storefrontBuildSchema, storefrontBuildStatusSchema, storefrontCheckSchema, storefrontCheckStatusSchema, storefrontCustomDomainStatusSchema, storefrontCustomHostnameProblem, storefrontDependencyFindingSchema, storefrontDeploymentLogSchema, storefrontDeploymentSchema, storefrontDeploymentStepSchema, storefrontDnsRecordSchema, storefrontDomainSchema, storefrontDomainTxtNameOf, storefrontEditPreviewLabelOf, storefrontEditPreviewSchema, storefrontEditSessionSchema, storefrontEditSessionStatusSchema, storefrontEditingSchema, storefrontFileConflictDetailsSchema, storefrontFileContentQuerySchema, storefrontFileContentSchema, storefrontFileDeleteResultSchema, storefrontFileEncodingSchema, storefrontFileEntrySchema, storefrontFileHashSchema, storefrontFileListQuerySchema, storefrontFileListSchema, storefrontFileMoveResultSchema, storefrontFilePathSchema, storefrontFileSearchResultSchema, storefrontFileWriteResultSchema, storefrontHostingSchema, storefrontPreviewLinkSchema, storefrontProvisioningSchema, storefrontRuleResultSchema, storefrontRuleSeveritySchema, storefrontSiteDomainSchema, storefrontSiteDomainsSchema, storefrontSiteSchema, storefrontSiteStatusSchema, storefrontSlugAvailabilityQuerySchema, storefrontSlugAvailabilitySchema, storefrontSlugSchema, storefrontSourceArchivePartSchema, storefrontSourceArchiveQuerySchema, storefrontSourceBlobsResultSchema, storefrontSourceModeSchema, storefrontSourceRefSchema, storefrontSourceReplacedSchema, storefrontSourceSchema, storefrontSuspensionSchema, storefrontTemplateSchema, storefrontVerifyReportSchema, storefrontVersionCreatedSchema, storefrontVersionSchema, storefrontVersionStatusSchema, storefrontVisibilitySchema, subscriptionLimitsSchema, subscriptionStatusSchema, subscriptionUsageSchema, tossPaymentsCredentialsInputSchema, trackingStageResponseSchema, trackingUpdateResultSchema, updateCouponRequestSchema, updateLoginProviderRequestSchema, updateLoginSettingsRequestSchema, updateMemberRoleRequestSchema, updatePaymentProviderRequestSchema, updatePaymentSettingsRequestSchema, updatePointPolicyRequestSchema, updateStoreRequestSchema, uploadExtensionOf, uploadPurposeSchema, uploadRejection, uploadRequestSchema, uploadStorefrontSourceBlobsRequestSchema, uploadTicketSchema, upsertPortOneProviderRequestSchema, upsertTossPaymentsProviderRequestSchema, variantStockRequestSchema, variantStockSchema, verifyPaymentProviderRequestSchema, webhookCreatedSchema, webhookDeliveryDetailSchema, webhookDeliveryErrorCodeSchema, webhookDeliveryListQuerySchema, webhookDeliveryResourceSchema, webhookDeliverySchema, webhookDeliveryStatusSchema, webhookEventSchema, webhookFailureReasonSchema, webhookRedeliverFailedResultSchema, webhookRequestHeaderSchema, webhookRequestSchema, webhookResourceTypeSchema, webhookSchema, webhookSecretRotatedSchema, webhookStatusSchema, webhookTestRequestSchema, webhookTestResultSchema, withdrawCustomerRequestSchema, writeDryRunResultSchema, writePreviewSchema, writeStorefrontFilesRequestSchema };
|
|
7452
|
+
export { APPROVAL_ALREADY_DECIDED_CODE, APPROVAL_REQUIRED_CODE, ApiError, ApprovalPendingError, BUSINESS_INFO_MAX_LENGTH, BUSINESS_NUMBER_PATTERN, CASH_RECEIPT_STATUS_VALUES, COLLECTION_BEST_SELLING_DAYS, COLLECTION_PREVIEW_SIZE, COLLECTION_PRODUCT_SORTS, COLLECTION_SALES_SORT_DEFAULT_DAYS, COLLECTION_SLUG_PATTERN, COLLECTION_TYPES, COUPON_CODE_PATTERN, COUPON_CONDITIONS_DEFAULTS, COUPON_TARGET_ALL, COUPON_TARGET_LIST_MAX, CUSTOM_INPUT_FORBIDDEN_WORDS, FULFILLMENT_RULES, MAX_ADDON_GROUPS, MAX_ANALYTICS_ALLOWED_ORIGINS, MAX_AUTO_TRANSITION_DAYS, MAX_COLLECTIONS, MAX_COLLECTION_BEST_SELLING_TOP, MAX_COLLECTION_CREATED_WITHIN_DAYS, MAX_COLLECTION_DESCRIPTION, MAX_COLLECTION_PRODUCTS, MAX_COLLECTION_PRODUCTS_PER_ADD, MAX_COLLECTION_RULES, MAX_COLLECTION_RULE_CATEGORIES, MAX_COLLECTION_TITLE, MAX_CUSTOM_INPUTS, MAX_CUSTOM_INPUT_LENGTH, MAX_OPTION_GROUPS, MAX_PRODUCT_IMAGES, MAX_SAVED_OPTION_SETS, MAX_SAVED_OPTION_SET_NAME, MAX_VALUES_PER_GROUP, MAX_VARIANTS, MCP_TELEMETRY_MAX_RESULTS, MIN_PAYMENT_AMOUNT, NO_COUPON_SETTLEMENT, NO_SHIPPING_BUNDLE_KEY, PAYMENT_ROUTING_EXCLUSION_CODES, POINT_ADJUSTMENT_MAX, POINT_EARN_RATE_BP_MAX, POINT_ENTRY_TYPES, POINT_EXPIRY_DAYS_MAX, POINT_EXPIRY_DAYS_MIN, POINT_LOT_SOURCES, POINT_POLICY_DEFAULTS, POINT_REVIEW_REWARD_MAX, POINT_USE_UNITS, PORTONE_CHANNEL_NAME_MAX_LENGTH, PORTONE_MAX_CHANNELS, PORTONE_MIN_CHANNELS, REFUND_POLICY_DEFAULTS, REFUND_POLICY_DELIVERY_FEE_KEYS, REMOTE_AREA_ZIP_RANGES, RESERVED_STOREFRONT_SLUGS, RESERVED_STORE_CODES, SHIPPING_POLICY_DEFAULTS, STOREFRONT_BLOCKED_PATH_SEGMENTS, STOREFRONT_BUILD_STAGES, STOREFRONT_BUILD_TERMINAL_STATUSES, STOREFRONT_CHECK_TERMINAL_STATUSES, STOREFRONT_CUSTOM_DOMAIN_LIMIT_DEFAULT, STOREFRONT_DOMAIN_DNS_GRACE_DAYS, STOREFRONT_DOMAIN_DNS_WAIT_DAYS, STOREFRONT_DOMAIN_TXT_LABEL, STOREFRONT_EDIT_ACTIVITY_TIMEOUT_MINUTES, STOREFRONT_EDIT_CAPACITY, STOREFRONT_EDIT_IDLE_MINUTES, STOREFRONT_EDIT_PREVIEW_SUFFIX, STOREFRONT_EDIT_START_STAGES, STOREFRONT_FILE_BATCH_MAX, STOREFRONT_FILE_MAX_BYTES, STOREFRONT_PATH_SEGMENT_PATTERN, STOREFRONT_PLATFORM_DOMAINS, STOREFRONT_PUBLIC_SUFFIXES, STOREFRONT_SEARCH_REGEX_MAX_LENGTH, STOREFRONT_SHOWCASE_SLUG_PREFIX, STOREFRONT_SITE_CREATE_LIMIT, STOREFRONT_SLUG_CHANGE_LIMIT, STOREFRONT_SLUG_CHANGE_WINDOW_DAYS, STOREFRONT_SLUG_HOLD_DAYS, STOREFRONT_SLUG_PATTERN, STOREFRONT_SOURCE_BLOB_BATCH_MAX, STOREFRONT_SOURCE_PART_BYTES, STOREFRONT_WORKSPACE_MAX_BYTES, STOREFRONT_WORKSPACE_MAX_FILES, STORE_CODE_PATTERN, STORE_ROLE_SCOPES, STORE_SCOPE_RESOURCES, STORE_SESSION_KEYS, TOSS_WIDGET_CLIENT_KEY_PATTERN, TOSS_WIDGET_KEY_MESSAGE, TOSS_WIDGET_SECRET_KEY_PATTERN, UPLOAD_PURPOSE_LIMITS, VARIANT_COUNT_WARNING, VARIANT_STOCK_EXCLUSIVE_MESSAGE, WEBHOOK_DEFAULT_TOLERANCE_SEC, WEBHOOK_DELIVERY_ID_HEADER, WEBHOOK_EVENT_ID_HEADER, WEBHOOK_EVENT_TYPE_HEADER, WEBHOOK_FAILURE_REASONS, WEBHOOK_HEADERS, WEBHOOK_PAYLOAD_EXCERPT_MAX_BYTES, WEBHOOK_RESOURCE_TYPES, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_USER_AGENT, addStorefrontDomainRequestSchema, addonGroupRequestSchema, addonGroupSchema, addonValueRequestSchema, addonValueSchema, addressChangeRequestListSchema, addressTypeSchema, agentPolicyDecisionSchema, allocateByWeight, analyticsChannelSchema, analyticsCheckoutOutcomeSchema, analyticsCheckoutSchema, analyticsDeviceRowSchema, analyticsDevicesSchema, analyticsFunnelStepSchema, analyticsOriginSchema, analyticsOverviewSchema, analyticsPagesQuerySchema, analyticsPagesSchema, analyticsProductRowSchema, analyticsProductSortSchema, analyticsProductsQuerySchema, analyticsProductsSchema, analyticsRangeQuerySchema, analyticsRealtimeSchema, analyticsSearchQuerySchema, analyticsSearchSchema, analyticsSourceGroupBySchema, analyticsSourceRowSchema, analyticsSourcesQuerySchema, analyticsSourcesSchema, analyticsTotalsSchema, apiLogErrorSchema, apiLogListQuerySchema, apiLogPageSchema, apiLogPrincipalSchema, apiLogPrincipalTypeSchema, apiLogSchema, apiLogStatusFilterSchema, apiLogSummarySchema, approvalDecisionRequestSchema, approvalListQuerySchema, approvalPageSchema, approvalRequestSchema, approvalStatusSchema, approveClaimResultSchema, auditActorSchema, auditActorTypeSchema, auditLogListQuerySchema, auditLogOutcomeSchema, auditLogPageSchema, auditLogSchema, auditLogSourceSchema, bestSellingRuleOf, buildAuthorizeUrl, buildQuery, bulkResultSchema, businessInfoPatchShape, businessInfoResponseShape, businessNumberSchema, cancelBySellerRequestSchema, cancelBySellerResultSchema, carrierSchema, cashReceiptSchema, categoryAttributeSchema, categoryCreateRequestSchema, categoryDeleteQuerySchema, categoryDeleteStrategySchema, categoryListQuerySchema, categoryPatchRequestSchema, categoryProductSortSchema, categorySchema, categorySearchResultSchema, categoryTreeNodeSchema, categoryWithPathSchema, changeStorefrontSlugRequestSchema, changeStorefrontTemplateRequestSchema, changeTypeSchema, claimDetailSchema, claimHoldResultSchema, claimListQuerySchema, claimReasonSchema, claimReturnAddressSchema, claimSchema, claimStatusSchema, claimTypeSchema, claimWebhookEventDataSchema, claimWebhookEventSchema, collectionCreateRequestSchema, collectionListQuerySchema, collectionPageSchema, collectionPatchRequestSchema, collectionPreviewRequestSchema, collectionPreviewSchema, collectionProductListQuerySchema, collectionProductSchema, collectionProductSortRequestSchema, collectionProductsAddRequestSchema, collectionProductsReplaceRequestSchema, collectionRuleCategoryIds, collectionRuleSchema, collectionRuleViewSchema, collectionRulesPredicate, collectionRulesSchema, collectionSchema, collectionStateCountsSchema, collectionStateOf, collectionStateSchema, compareBySales, consentActionSchema, consentKindSchema, consentSourceSchema, couponBenefitSchema, couponConditionsInputSchema, couponConditionsSchema, couponDiscountOf, couponIssueListQuerySchema, couponIssueMethodSchema, couponIssueSchema, couponIssueStatusSchema, couponKindSchema, couponListQuerySchema, couponRedemptionListQuerySchema, couponRedemptionSchema, couponRejectReasonSchema, couponRuleSchema, couponSchema, couponStatsSchema, couponStatusSchema, couponTargetInputSchema, couponTargetSchema, createCouponRequestSchema, createPkcePair, createStoreClient, createStoreSession, createStorefrontEditPreviewLinkRequestSchema, createStorefrontPreviewLinkRequestSchema, createStorefrontSiteRequestSchema, createStorefrontVersionRequestSchema, customInputLabelForbiddenWord, customInputRequestSchema, customInputSchema, customInputValueSchema, customerAddressSchema, customerConsentListQuerySchema, customerConsentSchema, customerConsentStateSchema, customerConsentsSchema, customerCouponSchema, customerDelegationRequestSchema, customerDelegationSchema, customerDetailSchema, customerInquiryCategorySchema, customerInquiryListQuerySchema, customerListQuerySchema, customerOrderSchema, customerPointsSchema, customerSortSchema, customerStatsSchema, customerSummarySchema, customerWithdrawalBlockedDetailsSchema, deleteStorefrontFileRequestSchema, deliveryBundleKeyOf, deliveryFeeWaiverSchema, deliveryInfoSchema, deliveryMethodSchema, deliveryStatusSchema, deliveryTypeSchema, descendantCategoryIdsOf, disableStorefrontHostingRequestSchema, discountRequestSchema, discountSchema, dispatchRequestSchema, easyPayProviderResponseSchema, easyPayProviderSchema, eventTypeSchema, exchangeAuthorizationCode, fulfillBulkRequestSchema, fulfillRequestSchema, fulfillmentRuleOf, fulfillmentTypeOf, fulfillmentTypeResponseSchema, fulfillmentTypeSchema, holdOrderItemRequestSchema, inquiryListQuerySchema, inquirySchema, inquiryWebhookEventDataSchema, inquiryWebhookEventSchema, invitationDeliveryStatusSchema, invitationListQuerySchema, invitationSchema, inviteMemberRequestSchema, isCouponTargetLine, isEditableStorefrontPath, isReservedStoreCode, isReservedStorefrontSlug, isShowcaseStorefrontSlug, isStoreScope, isWebOrigin, issueCouponRequestSchema, issueCouponResultSchema, liveGateConditionCodeSchema, liveGateConditionSchema, liveGateErrorDetailsSchema, liveGateSchema, loginProviderSchema, loginProviderStatusSchema, loginProviderTestSchema, loginSettingsSchema, maskedSecretSchema, matchesCollectionRules, mcpRuleResultSchema, mcpToolEventSchema, moveStorefrontFileRequestSchema, myAccountSchema, myStoreSchema, normalizeBusinessNumber, normalizeCouponCode, normalizeStorefrontHostname, normalizeStorefrontPath, oauthTokenResponseSchema, openFulfillmentUnion, optionGroupKindSchema, optionGroupRequestSchema, optionGroupSchema, optionModelRequestSchema, optionModelSchema, optionSelectionSchema, optionSortSchema, optionValueRequestSchema, optionValueSchema, orderCanceledWebhookEventDataSchema, orderCanceledWebhookEventSchema, orderDiscountSchema, orderFulfilledWebhookEventDataSchema, orderFulfilledWebhookEventSchema, orderItemFulfillmentSchema, orderItemFulfillmentSnapshotResponseSchema, orderItemFulfillmentSnapshotSchema, orderItemListQuerySchema, orderItemMemoResultSchema, orderItemPageSchema, orderItemSchema, orderItemStatusSchema, orderListQuerySchema, orderSchema, orderSummaryPageSchema, orderSummarySchema, orderWebhookEventDataSchema, orderWebhookEventSchema, pageInfoSchema, pageQueryShape, pageSchema, paymentAttemptRecordSchema, paymentAttemptStatusSchema, paymentCredentialSetSchema, paymentFailureWarningSchema, paymentListQuerySchema, paymentProviderSchema, paymentProviderVerificationSchema, paymentRecordDetailSchema, paymentRecordPageSchema, paymentRecordSchema, paymentRecordStatusSchema, paymentRefundRecordSchema, paymentSettingsSchema, pgEnvironmentSchema, pgPaymentMethodSchema, pgProviderSchema, pgVerificationResultSchema, planCodeSchema, planEntitlementsSchema, planErrorDetailsSchema, pointAdjustmentRequestSchema, pointAdjustmentResultSchema, pointEarnOf, pointEarnRateBpSchema, pointEarningEnabled, pointEntrySchema, pointExpiresAtOf, pointHistoryQuerySchema, pointLotSchema, pointPolicyNoticeSchema, pointPolicySchema, pointRestoreExpiresAtOf, pointUseOf, pointUsePolicySchema, policyDocumentUrlSchema, policyVersionSchema, portOneChannelSchema, portOneCredentialsInputSchema, productCreateRequestSchema, productFulfillmentCreateSchema, productFulfillmentResponseSchema, productFulfillmentSchema, productFulfillmentUpdateSchema, productImageRejection, productImageUrlSchema, productListQuerySchema, productOutOfStockWebhookEventDataSchema, productOutOfStockWebhookEventSchema, productPatchRequestSchema, productRefundPolicyOverride, productRefundPolicyPatchSchema, productReplaceRequestSchema, productSchema, productSortSchema, productStatusSchema, productSummarySchema, productVariantRequestSchema, productVariantSchema, proratedPaidRefundBase, proratedPointRefund, proratedRefundBase, publicPlanSchema, publicPlansSchema, publishStorefrontVersionRequestSchema, purchaseDecisionExtendResultSchema, purchaseDecisionRequestResultSchema, purchaseEarnPolicySchema, purchaseEarnRateOf, quoteDelivery, quotePricing, rankBestSelling, refreshUserToken, refundPolicyPatchSchema, refundPolicySchema, rejectClaimRequestSchema, remoteAreaLabelOf, remoteAreaOf, remoteAreaSchema, remoteSurchargeOf, replaceStorefrontSourceRequestSchema, requiresCollection, requiresShipping, resolvePointPolicy, resolveRefundPolicy, resolveShippingPolicy, responsePlanCodeSchema, responsePointEntryTypeSchema, reviewListQuerySchema, reviewReportResultSchema, reviewRewardPointOf, reviewRewardPolicySchema, reviewSchema, reviewSortSchema, reviewWebhookEventDataSchema, reviewWebhookEventSchema, rollbackStorefrontRequestSchema, runStorefrontCheckRequestSchema, salesReportGroupBySchema, salesReportQuerySchema, salesReportRowSchema, salesReportSchema, salesTotalsSchema, saveLoginProviderRequestSchema, savedCustomInputRequestSchema, savedCustomInputSchema, savedOptionGroupRequestSchema, savedOptionGroupSchema, savedOptionSetCompositionSchema, savedOptionSetFromProductRequestSchema, savedOptionSetFromProductResultSchema, savedOptionSetListQuerySchema, savedOptionSetRequestSchema, savedOptionSetSchema, savedOptionSetSortSchema, savedOptionValueRequestSchema, savedOptionValueSchema, scopeAccessSchema, searchStorefrontFilesRequestSchema, sellerAddressListQuerySchema, sellerAddressRequestSchema, sellerAddressSchema, sellerCustomerInquirySchema, setStorefrontVisibilityRequestSchema, settleCouponShortfall, settlementDetailQuerySchema, settlementDetailSchema, settlementListQuerySchema, settlementStatusSchema, settlementSummarySchema, settlementWithDetailsSchema, shippingAddressSchema, shippingPolicyPatchSchema, shippingPolicySchema, splitRefund, storeCodeSchema, storeMemberRoleUpdatedSchema, storeMemberSchema, storePointPolicySchema, storeRoleSchema, storeSchema, storeScopeResourceSchema, storeSubscriptionSchema, storefrontBuildDependenciesSchema, storefrontBuildListQuerySchema, storefrontBuildSchema, storefrontBuildStatusSchema, storefrontCheckSchema, storefrontCheckStatusSchema, storefrontCustomDomainStatusSchema, storefrontCustomHostnameProblem, storefrontDependencyFindingSchema, storefrontDeploymentLogSchema, storefrontDeploymentSchema, storefrontDeploymentStepSchema, storefrontDnsRecordSchema, storefrontDomainSchema, storefrontDomainTxtNameOf, storefrontEditPreviewLabelOf, storefrontEditPreviewSchema, storefrontEditSessionSchema, storefrontEditSessionStatusSchema, storefrontEditingSchema, storefrontFileConflictDetailsSchema, storefrontFileContentQuerySchema, storefrontFileContentSchema, storefrontFileDeleteResultSchema, storefrontFileEncodingSchema, storefrontFileEntrySchema, storefrontFileHashSchema, storefrontFileListQuerySchema, storefrontFileListSchema, storefrontFileMoveResultSchema, storefrontFilePathSchema, storefrontFileSearchResultSchema, storefrontFileWriteResultSchema, storefrontHostingSchema, storefrontPreviewLinkSchema, storefrontProvisioningSchema, storefrontRuleResultSchema, storefrontRuleSeveritySchema, storefrontSiteDomainSchema, storefrontSiteDomainsSchema, storefrontSiteSchema, storefrontSiteStatusSchema, storefrontSlugAvailabilityQuerySchema, storefrontSlugAvailabilitySchema, storefrontSlugSchema, storefrontSourceArchivePartSchema, storefrontSourceArchiveQuerySchema, storefrontSourceBlobsResultSchema, storefrontSourceModeSchema, storefrontSourceRefSchema, storefrontSourceReplacedSchema, storefrontSourceSchema, storefrontSuspensionSchema, storefrontTemplateSchema, storefrontVerifyReportSchema, storefrontVersionCreatedSchema, storefrontVersionSchema, storefrontVersionStatusSchema, storefrontVisibilitySchema, subscriptionLimitsSchema, subscriptionStatusSchema, subscriptionUsageSchema, tossPaymentsCredentialsInputSchema, trackingStageResponseSchema, trackingUpdateResultSchema, updateCouponRequestSchema, updateLoginProviderRequestSchema, updateLoginSettingsRequestSchema, updateMemberRoleRequestSchema, updatePaymentProviderRequestSchema, updatePaymentSettingsRequestSchema, updatePointPolicyRequestSchema, updateStoreRequestSchema, uploadExtensionOf, uploadPurposeSchema, uploadRejection, uploadRequestSchema, uploadStorefrontSourceBlobsRequestSchema, uploadTicketSchema, upsertPortOneProviderRequestSchema, upsertTossPaymentsProviderRequestSchema, variantStockRequestSchema, variantStockSchema, verifyPaymentProviderRequestSchema, webhookCreatedSchema, webhookDeliveryDetailSchema, webhookDeliveryErrorCodeSchema, webhookDeliveryListQuerySchema, webhookDeliveryResourceSchema, webhookDeliverySchema, webhookDeliveryStatusSchema, webhookEventSchema, webhookFailureReasonSchema, webhookRedeliverFailedResultSchema, webhookRequestHeaderSchema, webhookRequestSchema, webhookResourceTypeSchema, webhookSchema, webhookSecretRotatedSchema, webhookStatusSchema, webhookTestRequestSchema, webhookTestResultSchema, withdrawCustomerRequestSchema, writeDryRunResultSchema, writePreviewSchema, writeStorefrontFilesRequestSchema };
|
package/package.json
CHANGED
|
@@ -28,7 +28,7 @@ export const COLLECTION_TYPES = ["MANUAL", "AUTOMATIC"] as const;
|
|
|
28
28
|
export type CollectionType = (typeof COLLECTION_TYPES)[number];
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
* 상품 정렬 — `MANUAL`은 직접 정한 순서(직접 선택 컬렉션만)다. `BEST_SELLING`(판매량순)은
|
|
31
|
+
* 상품 정렬 — `MANUAL`은 직접 정한 순서(직접 선택 컬렉션만)다. `BEST_SELLING`(판매량순)은 판매 수량이 많은 순이다(M3).
|
|
32
32
|
* 저장 값 전체 목록이고, 쓰기에서 받는 값은 `collectionProductSortRequestSchema`다.
|
|
33
33
|
*/
|
|
34
34
|
export const COLLECTION_PRODUCT_SORTS = [
|
|
@@ -44,9 +44,19 @@ export const COLLECTION_PRODUCT_SORTS = [
|
|
|
44
44
|
export type CollectionProductSort = (typeof COLLECTION_PRODUCT_SORTS)[number];
|
|
45
45
|
|
|
46
46
|
export const collectionProductSortRequestSchema = z
|
|
47
|
-
.enum([
|
|
47
|
+
.enum([
|
|
48
|
+
"MANUAL",
|
|
49
|
+
"LATEST",
|
|
50
|
+
"BEST_SELLING",
|
|
51
|
+
"PRICE_ASC",
|
|
52
|
+
"PRICE_DESC",
|
|
53
|
+
"REVIEW_COUNT",
|
|
54
|
+
"RATING_DESC",
|
|
55
|
+
"RECOMMEND",
|
|
56
|
+
])
|
|
48
57
|
.describe(
|
|
49
|
-
"스토어프론트 상품 기본 정렬. `MANUAL`(직접 정한 순서)·`LATEST`(최신순)·`PRICE_ASC`·`PRICE_DESC`·`REVIEW_COUNT`·`RATING_DESC`·`RECOMMEND`(추천순)"
|
|
58
|
+
"스토어프론트 상품 기본 정렬. `MANUAL`(직접 정한 순서)·`LATEST`(최신순)·`BEST_SELLING`(판매량순)·`PRICE_ASC`·`PRICE_DESC`·`REVIEW_COUNT`·`RATING_DESC`·`RECOMMEND`(추천순). " +
|
|
59
|
+
"판매량순의 기간은 판매량 상위 조건의 기간이고, 조건이 없으면 최근 30일이다",
|
|
50
60
|
);
|
|
51
61
|
|
|
52
62
|
/** 노출 상태 — 노출 여부와 기간에서 나온 값이다. 숨김이 기간보다 앞선다 */
|
|
@@ -73,6 +83,13 @@ export const MAX_COLLECTION_RULE_CATEGORIES = 20;
|
|
|
73
83
|
export const MAX_COLLECTION_CREATED_WITHIN_DAYS = 365;
|
|
74
84
|
/** 미리보기(`POST /v1/collections/preview`)가 싣는 상품 최대 개수 */
|
|
75
85
|
export const COLLECTION_PREVIEW_SIZE = 20;
|
|
86
|
+
/** 판매량 상위 조건의 기간 선택지(일, 오늘 포함 한국 날짜) */
|
|
87
|
+
export const COLLECTION_BEST_SELLING_DAYS = [7, 30, 90] as const;
|
|
88
|
+
export type CollectionBestSellingDays = (typeof COLLECTION_BEST_SELLING_DAYS)[number];
|
|
89
|
+
/** 판매량 상위 조건이 담는 상품 최대 개수 */
|
|
90
|
+
export const MAX_COLLECTION_BEST_SELLING_TOP = 100;
|
|
91
|
+
/** 판매량순(`BEST_SELLING`) 정렬의 기간 — 판매량 상위 조건이 없을 때 쓴다 */
|
|
92
|
+
export const COLLECTION_SALES_SORT_DEFAULT_DAYS: CollectionBestSellingDays = 30;
|
|
76
93
|
|
|
77
94
|
const createdWithinDaysRuleSchema = z.object({
|
|
78
95
|
field: z.literal("createdWithinDays"),
|
|
@@ -106,9 +123,23 @@ const discountedRuleSchema = z.object({
|
|
|
106
123
|
value: z.literal(true).describe("즉시할인이 지금 적용되는 상품"),
|
|
107
124
|
});
|
|
108
125
|
|
|
126
|
+
const bestSellingRuleSchema = z.object({
|
|
127
|
+
field: z.literal("bestSelling"),
|
|
128
|
+
days: z
|
|
129
|
+
.union([z.literal(7), z.literal(30), z.literal(90)])
|
|
130
|
+
.describe("판매량을 세는 기간(일). 7·30·90 중 하나이고 오늘을 포함한 한국 날짜 기준이다"),
|
|
131
|
+
top: z
|
|
132
|
+
.number()
|
|
133
|
+
.int()
|
|
134
|
+
.min(1)
|
|
135
|
+
.max(MAX_COLLECTION_BEST_SELLING_TOP)
|
|
136
|
+
.describe("담을 상품 수(1~100). 다른 조건을 만족하는 상품 중 판매 수량 상위 N개다"),
|
|
137
|
+
});
|
|
138
|
+
|
|
109
139
|
/**
|
|
110
140
|
* 조건 하나 — `field`로 가른다. 가격은 즉시할인을 반영한 판매가(`discountedPrice ?? salePrice`)다.
|
|
111
|
-
* 판매량 상위(`bestSelling`)는
|
|
141
|
+
* 판매량 상위(`bestSelling`)는 술어가 아니라 순위 자르기다. 다른 조건을 모두 만족한 상품 중 판매 수량 상위 N개만 남긴다(`rankBestSelling`).
|
|
142
|
+
* 판매 수량은 실결제 주문의 결제 수량에서 취소·반품 수량을 뺀 값이고, 날짜는 주문 시각의 한국 날짜다. 집계는 최대 10분 늦다.
|
|
112
143
|
*/
|
|
113
144
|
export const collectionRuleSchema = z
|
|
114
145
|
.discriminatedUnion("field", [
|
|
@@ -116,6 +147,7 @@ export const collectionRuleSchema = z
|
|
|
116
147
|
categoryRuleSchema,
|
|
117
148
|
priceRuleSchema,
|
|
118
149
|
discountedRuleSchema,
|
|
150
|
+
bestSellingRuleSchema,
|
|
119
151
|
])
|
|
120
152
|
.superRefine((rule, ctx) => {
|
|
121
153
|
if (rule.field !== "price") return;
|
|
@@ -163,6 +195,7 @@ export const collectionRuleViewSchema = z.union([
|
|
|
163
195
|
categoryRuleSchema,
|
|
164
196
|
priceRuleSchema,
|
|
165
197
|
discountedRuleSchema,
|
|
198
|
+
bestSellingRuleSchema,
|
|
166
199
|
z.looseObject({ field: z.string() }),
|
|
167
200
|
]);
|
|
168
201
|
|
|
@@ -213,6 +246,7 @@ export function descendantCategoryIdsOf(
|
|
|
213
246
|
/**
|
|
214
247
|
* 조건 판정 함수를 만든다 — 모든 조건을 만족해야 true다(AND). 카테고리 트리는 여기서 한 번만 푼다.
|
|
215
248
|
* 알 수 없는 조건(`field`)은 만족하지 않는 것으로 본다. 모르는 조건을 건너뛰면 상품이 예고 없이 늘어난다.
|
|
249
|
+
* 판매량 상위(`bestSelling`)는 여기서 모두 통과시킨다. 순위 자르기는 판매량을 아는 호출부가 `rankBestSelling`으로 한다.
|
|
216
250
|
* 판매 상태는 보지 않는다. 판매 중만 거르는 것은 호출부다.
|
|
217
251
|
*/
|
|
218
252
|
export function collectionRulesPredicate(
|
|
@@ -243,6 +277,8 @@ export function collectionRulesPredicate(
|
|
|
243
277
|
case "discounted":
|
|
244
278
|
return (product) =>
|
|
245
279
|
product.discountedPrice !== null && product.discountedPrice < product.salePrice;
|
|
280
|
+
case "bestSelling":
|
|
281
|
+
return () => true;
|
|
246
282
|
default:
|
|
247
283
|
return () => false;
|
|
248
284
|
}
|
|
@@ -259,6 +295,45 @@ export function matchesCollectionRules(
|
|
|
259
295
|
return collectionRulesPredicate(rules, context)(product);
|
|
260
296
|
}
|
|
261
297
|
|
|
298
|
+
/** 판매량 상위 조건 — 없으면 null. 같은 조건은 한 번만 쓰므로 첫 번째다 */
|
|
299
|
+
export function bestSellingRuleOf(
|
|
300
|
+
rules: readonly CollectionRuleView[],
|
|
301
|
+
): { days: CollectionBestSellingDays; top: number } | null {
|
|
302
|
+
for (const rule of rules) {
|
|
303
|
+
const parsed = bestSellingRuleSchema.safeParse(rule);
|
|
304
|
+
if (parsed.success) return { days: parsed.data.days, top: parsed.data.top };
|
|
305
|
+
}
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* 판매량 비교 — 판매 수량이 많은 순, 같으면 최근 등록 순, 그것도 같으면 상품 id 순이다. 결과가 입력 순서에 기대지 않는다.
|
|
311
|
+
* `sales`에 없는 상품은 0개다.
|
|
312
|
+
*/
|
|
313
|
+
export function compareBySales<T extends { productId: string; createdAt: string }>(
|
|
314
|
+
sales: ReadonlyMap<string, number>,
|
|
315
|
+
): (a: T, b: T) => number {
|
|
316
|
+
return (a, b) =>
|
|
317
|
+
(sales.get(b.productId) ?? 0) - (sales.get(a.productId) ?? 0) ||
|
|
318
|
+
Date.parse(b.createdAt) - Date.parse(a.createdAt) ||
|
|
319
|
+
(a.productId < b.productId ? -1 : a.productId > b.productId ? 1 : 0);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* 판매량 상위 자르기 — 다른 조건을 통과한 상품 중 판매 수량이 1개 이상인 상품을 `compareBySales` 순으로 `top`개 남긴다.
|
|
324
|
+
* 판매가 없는 상품은 넣지 않는다.
|
|
325
|
+
*/
|
|
326
|
+
export function rankBestSelling<T extends { productId: string; createdAt: string }>(
|
|
327
|
+
products: readonly T[],
|
|
328
|
+
sales: ReadonlyMap<string, number>,
|
|
329
|
+
top: number,
|
|
330
|
+
): T[] {
|
|
331
|
+
return products
|
|
332
|
+
.filter((product) => (sales.get(product.productId) ?? 0) > 0)
|
|
333
|
+
.sort(compareBySales(sales))
|
|
334
|
+
.slice(0, Math.max(0, top));
|
|
335
|
+
}
|
|
336
|
+
|
|
262
337
|
/** 조건이 참조하는 카테고리 id — 카테고리 삭제의 참조 검사에 쓴다 */
|
|
263
338
|
export function collectionRuleCategoryIds(rules: readonly CollectionRuleView[]): string[] {
|
|
264
339
|
const ids: string[] = [];
|
|
@@ -288,6 +363,14 @@ export const collectionSchema = z.object({
|
|
|
288
363
|
metaTitle: z.string().nullable(),
|
|
289
364
|
metaDescription: z.string().nullable(),
|
|
290
365
|
state: collectionStateSchema.describe("지금 노출 상태"),
|
|
366
|
+
salesComputedAt: z
|
|
367
|
+
.string()
|
|
368
|
+
.nullable()
|
|
369
|
+
.default(null)
|
|
370
|
+
.describe(
|
|
371
|
+
"판매량 기준 시각. 판매량 상위 조건이나 판매량순 정렬을 쓰는 컬렉션은 이 시각까지의 주문을 센다(최대 10분 늦다). " +
|
|
372
|
+
"판매량을 쓰지 않거나 아직 집계 전이면 null",
|
|
373
|
+
),
|
|
291
374
|
productCount: z
|
|
292
375
|
.number()
|
|
293
376
|
.int()
|
|
@@ -347,7 +430,7 @@ const periodRefine = (
|
|
|
347
430
|
/**
|
|
348
431
|
* `POST /v1/collections` — 컬렉션을 만든다. `slug`를 생략하면 `c-{id 뒤 8자}`로 만든다.
|
|
349
432
|
* 직접 선택(`MANUAL`)은 `productIds`가 처음 담을 상품과 순서다. 조건 자동(`AUTOMATIC`)은 `rules`가 있어야 하고 `productIds`를 받지 않는다.
|
|
350
|
-
* `productSort`를 생략하면 직접 선택은 `MANUAL`, 조건 자동은 `LATEST
|
|
433
|
+
* `productSort`를 생략하면 직접 선택은 `MANUAL`, 조건 자동은 `LATEST`(판매량 상위 조건이 있으면 `BEST_SELLING`)다. 조건 자동은 `MANUAL`을 쓸 수 없다.
|
|
351
434
|
*/
|
|
352
435
|
export const collectionCreateRequestSchema = z
|
|
353
436
|
.object({
|
|
@@ -365,7 +448,7 @@ export const collectionCreateRequestSchema = z
|
|
|
365
448
|
productSort: commonFields.productSort
|
|
366
449
|
.optional()
|
|
367
450
|
.describe(
|
|
368
|
-
"스토어프론트 상품 기본 정렬. 생략하면 직접 선택은 `MANUAL`, 조건 자동은 `LATEST
|
|
451
|
+
"스토어프론트 상품 기본 정렬. 생략하면 직접 선택은 `MANUAL`, 조건 자동은 `LATEST`(판매량 상위 조건이 있으면 `BEST_SELLING`)다. 조건 자동은 `MANUAL`을 쓸 수 없다",
|
|
369
452
|
),
|
|
370
453
|
visible: commonFields.visible.default(true),
|
|
371
454
|
startsAt: commonFields.startsAt,
|
|
@@ -483,7 +566,9 @@ export const collectionPreviewRequestSchema = z.object({
|
|
|
483
566
|
rules: collectionRulesSchema,
|
|
484
567
|
productSort: collectionProductSortRequestSchema
|
|
485
568
|
.optional()
|
|
486
|
-
.describe(
|
|
569
|
+
.describe(
|
|
570
|
+
"미리보기 순서. 생략하면 `LATEST`(판매량 상위 조건이 있으면 `BEST_SELLING`)이고, `MANUAL`이면 `LATEST`다",
|
|
571
|
+
),
|
|
487
572
|
});
|
|
488
573
|
|
|
489
574
|
export type CollectionPreviewRequest = z.infer<typeof collectionPreviewRequestSchema>;
|
|
@@ -492,6 +577,13 @@ export type CollectionPreviewRequest = z.infer<typeof collectionPreviewRequestSc
|
|
|
492
577
|
export const collectionPreviewSchema = z.object({
|
|
493
578
|
count: z.number().int().describe("조건을 만족하는 판매 중 상품 수(조회 시각 기준)"),
|
|
494
579
|
products: z.array(collectionProductSchema).describe("앞 20개(정렬 순)"),
|
|
580
|
+
salesComputedAt: z
|
|
581
|
+
.string()
|
|
582
|
+
.nullable()
|
|
583
|
+
.default(null)
|
|
584
|
+
.describe(
|
|
585
|
+
"판매량 기준 시각. 판매량 상위 조건이나 판매량순 정렬을 쓰면 이 시각까지의 주문을 센다. 판매량을 쓰지 않거나 집계 전이면 null",
|
|
586
|
+
),
|
|
495
587
|
});
|
|
496
588
|
|
|
497
589
|
export type CollectionPreview = z.infer<typeof collectionPreviewSchema>;
|
package/src/schemas/promotion.ts
CHANGED
|
@@ -316,7 +316,7 @@ export interface PricingResult {
|
|
|
316
316
|
pointAmount: number;
|
|
317
317
|
/** 지금 쓸 수 있는 최대 적립금 — 주문서 안내값(잔액을 모두 요청했을 때의 금액). 적립금 입력이 없으면 0 */
|
|
318
318
|
pointMaxUsable: number;
|
|
319
|
-
/** 요청보다 적게 썼다면 그 이유 — `MIN_PAYMENT`: 결제
|
|
319
|
+
/** 요청보다 적게 썼다면 그 이유 — `MIN_PAYMENT`: 남는 결제 금액이 1~99원이라 100원을 남기려고 줄였다(전액이면 0원 결제) */
|
|
320
320
|
pointAdjustReason: "MIN_PAYMENT" | null;
|
|
321
321
|
/** 요청했지만 쓰지 못했다면 그 이유 */
|
|
322
322
|
pointRejectReason: PointRejectReason | null;
|
|
@@ -662,8 +662,10 @@ export function quotePricing(input: PricingInput): PricingResult {
|
|
|
662
662
|
}
|
|
663
663
|
|
|
664
664
|
/**
|
|
665
|
-
* 사용 적립금 금액(순수) — 요청·잔액·최대
|
|
666
|
-
*
|
|
665
|
+
* 사용 적립금 금액(순수) — 요청·잔액·최대 비율 중 작은 값을 쓴다(#93 P3·P4).
|
|
666
|
+
* - 결제 금액 전체를 덮을 수 있으면 전액을 쓴다(0원 결제, 이때만 사용 단위를 보지 않는다)
|
|
667
|
+
* - 그 밖에는 사용 단위로 내리고, 남는 결제 금액이 1~99원이면 적립금을 줄여 100원을 남긴다(`MIN_PAYMENT`)
|
|
668
|
+
* 최소 보유액·최소 사용액에 못 미치면 0이다.
|
|
667
669
|
*/
|
|
668
670
|
export function pointUseOf(
|
|
669
671
|
points: PricingPoints | null,
|
|
@@ -680,27 +682,38 @@ export function pointUseOf(
|
|
|
680
682
|
const unit = Math.max(1, Math.floor(rules.unit));
|
|
681
683
|
const base = amounts.productPaid + (rules.includeDeliveryFee ? amounts.deliveryPaid : 0);
|
|
682
684
|
const byRatio = Math.floor((base * rules.maxRatioBp) / 10_000);
|
|
683
|
-
// 결제 금액은 0원 또는 100원 이상이어야 하고, 지금은 0원 결제를 받지 않으므로 100원을 남긴다
|
|
684
|
-
const byPayment = Math.max(0, amounts.total - MIN_PAYMENT_AMOUNT);
|
|
685
685
|
const balance = Math.max(0, points.balance);
|
|
686
|
+
const total = Math.max(0, amounts.total);
|
|
686
687
|
const floorUnit = (value: number) => Math.floor(Math.max(0, value) / unit) * unit;
|
|
688
|
+
/** 상한 `cap`으로 쓸 수 있는 금액 — 전액이면 0원 결제, 아니면 단위 내림 + 100원 남기기 */
|
|
689
|
+
const usableWithin = (cap: number): { amount: number; adjusted: boolean } => {
|
|
690
|
+
if (total > 0 && cap >= total) return { amount: total, adjusted: false };
|
|
691
|
+
const amount = floorUnit(Math.min(cap, total));
|
|
692
|
+
const remaining = total - amount;
|
|
693
|
+
if (remaining > 0 && remaining < MIN_PAYMENT_AMOUNT) {
|
|
694
|
+
return { amount: floorUnit(total - MIN_PAYMENT_AMOUNT), adjusted: true };
|
|
695
|
+
}
|
|
696
|
+
return { amount, adjusted: false };
|
|
697
|
+
};
|
|
687
698
|
const eligible = balance >= rules.minBalance;
|
|
688
|
-
const ceiling = Math.min(balance, byRatio
|
|
689
|
-
const maxUsable = eligible &&
|
|
699
|
+
const ceiling = usableWithin(Math.min(balance, byRatio)).amount;
|
|
700
|
+
const maxUsable = eligible && ceiling > 0 && ceiling >= rules.minAmount ? ceiling : 0;
|
|
690
701
|
const requested = Math.max(0, Math.floor(points.requested));
|
|
691
702
|
if (requested === 0) return { ...none, maxUsable };
|
|
692
703
|
if (!eligible) return { amount: 0, maxUsable, adjustReason: null, rejectReason: "MIN_BALANCE" };
|
|
693
|
-
const
|
|
694
|
-
if (amount <= 0) {
|
|
704
|
+
const used = usableWithin(Math.min(requested, balance, byRatio));
|
|
705
|
+
if (used.amount <= 0) {
|
|
695
706
|
return { amount: 0, maxUsable, adjustReason: null, rejectReason: "NOT_PAYABLE" };
|
|
696
707
|
}
|
|
697
|
-
if (amount < rules.minAmount) {
|
|
708
|
+
if (used.amount < rules.minAmount) {
|
|
698
709
|
return { amount: 0, maxUsable, adjustReason: null, rejectReason: "MIN_AMOUNT" };
|
|
699
710
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
711
|
+
return {
|
|
712
|
+
amount: used.amount,
|
|
713
|
+
maxUsable,
|
|
714
|
+
adjustReason: used.adjusted ? "MIN_PAYMENT" : null,
|
|
715
|
+
rejectReason: null,
|
|
716
|
+
};
|
|
704
717
|
}
|
|
705
718
|
|
|
706
719
|
// ─── 환불 정산: 조건 미달 차감 ─────────────────────────────
|