@sayren/store-sdk 0.1.0

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.
@@ -0,0 +1,233 @@
1
+ import { z } from "zod";
2
+ import { changeTypeSchema, orderItemStatusSchema, type PageParams, pageSchema } from "./common";
3
+
4
+ export const orderSummarySchema = z.object({
5
+ orderId: z.string(),
6
+ ordererName: z.string(),
7
+ itemCount: z.number().int(),
8
+ totalAmount: z.number().int(),
9
+ representativeStatus: orderItemStatusSchema,
10
+ orderedAt: z.string(),
11
+ testPayment: z
12
+ .boolean()
13
+ .describe(
14
+ "테스트 결제(샌드박스 결제) 주문인가. true면 실제로 돈이 오가지 않았어요. 상품을 발송하지 않도록 주의하세요",
15
+ ),
16
+ });
17
+
18
+ export type OrderSummary = z.infer<typeof orderSummarySchema>;
19
+
20
+ export const shippingAddressSchema = z.object({
21
+ receiverName: z.string(),
22
+ phone: z.string(),
23
+ zipCode: z.string(),
24
+ address1: z.string(),
25
+ address2: z.string().nullish(),
26
+ deliveryMemo: z.string().nullish(),
27
+ entranceCode: z.string().nullish(),
28
+ });
29
+
30
+ export type ShippingAddress = z.infer<typeof shippingAddressSchema>;
31
+
32
+ export const orderItemSchema = z.object({
33
+ orderItemId: z.string(),
34
+ orderId: z.string(),
35
+ status: orderItemStatusSchema,
36
+ claimStatus: z.enum(["CANCEL_REQUESTED", "RETURN_REQUESTED", "EXCHANGE_REQUESTED"]).nullable(),
37
+ productId: z.string(),
38
+ productName: z.string(),
39
+ optionId: z.string().nullable(),
40
+ optionName: z.string().nullable(),
41
+ sellerCode: z.string().nullable(),
42
+ quantity: z.number().int(),
43
+ unitPrice: z.number().int(),
44
+ discountAmount: z.number().int(),
45
+ totalPrice: z.number().int(),
46
+ hold: z.object({ reason: z.string(), expectedDispatchDate: z.string() }).nullable(),
47
+ autoDecisionDate: z.string().nullable(),
48
+ sellerMemo: z.string().nullable(),
49
+ orderedAt: z.string(),
50
+ lastChangedAt: z.string(),
51
+ lastChangedType: changeTypeSchema,
52
+ testPayment: z
53
+ .boolean()
54
+ .describe(
55
+ "소속 주문이 테스트 결제(샌드박스 결제) 주문인가. true면 실제로 돈이 오가지 않았어요",
56
+ ),
57
+ });
58
+
59
+ export type OrderItem = z.infer<typeof orderItemSchema>;
60
+
61
+ export const orderSchema = z.object({
62
+ orderId: z.string(),
63
+ orderedAt: z.string(),
64
+ orderer: z.object({
65
+ name: z.string(),
66
+ phone: z.string(),
67
+ email: z.email().optional(),
68
+ }),
69
+ shippingAddress: shippingAddressSchema,
70
+ payment: z.object({
71
+ method: z
72
+ .enum(["CARD", "BANK_TRANSFER", "VIRTUAL_ACCOUNT", "MOBILE", "POINT", "MIXED"])
73
+ .describe(
74
+ "method는 호환용이며 간편결제를 CARD로 표시한다. 실제 수단은 approvedMethod를 본다",
75
+ ),
76
+ approvedMethod: z
77
+ .string()
78
+ .nullable()
79
+ .optional()
80
+ .default(null)
81
+ .describe(
82
+ "실제 결제수단. method는 호환용이며 간편결제를 CARD로 표시한다. 실제 수단은 approvedMethod를 본다. " +
83
+ "현재 값은 `pgPaymentMethodSchema`(`PgPaymentMethod`: CARD·BANK_TRANSFER·VIRTUAL_ACCOUNT·MOBILE·EASY_PAY)이고 " +
84
+ "매출 리포트·스토어프론트·환불 원장과 같은 값이다. 값이 추가될 수 있어 문자열로 받는다. PG가 알려 주지 않았으면 요청 수단, " +
85
+ "시도 기록이 없는 오래된 주문은 null. 서버는 항상 싣는다",
86
+ ),
87
+ productAmount: z.number().int(),
88
+ deliveryFee: z.number().int(),
89
+ discountAmount: z.number().int(),
90
+ totalAmount: z.number().int(),
91
+ paidAt: z.string().nullable(),
92
+ }),
93
+ testPayment: z
94
+ .boolean()
95
+ .describe(
96
+ "테스트 결제(샌드박스 결제) 주문인가. true면 실제로 돈이 오가지 않았어요. 상품을 발송하지 않도록 주의하세요",
97
+ ),
98
+ items: z.array(orderItemSchema),
99
+ });
100
+
101
+ export type Order = z.infer<typeof orderSchema>;
102
+
103
+ /** 주문 목록 응답 — `GET /v1/orders` */
104
+ export const orderSummaryPageSchema = pageSchema(orderSummarySchema);
105
+ export type OrderSummaryPage = z.infer<typeof orderSummaryPageSchema>;
106
+
107
+ /** 주문상품 변경 목록 응답 — `GET /v1/order-items` */
108
+ export const orderItemPageSchema = pageSchema(orderItemSchema);
109
+ export type OrderItemPage = z.infer<typeof orderItemPageSchema>;
110
+
111
+ const testPaymentQuery = z
112
+ .enum(["true", "false"])
113
+ .optional()
114
+ .describe(
115
+ "테스트 결제(샌드박스 결제) 필터. `true`면 테스트 결제만, `false`면 실결제만, 생략하면 전부예요",
116
+ );
117
+
118
+ const pageQuery = {
119
+ page: z.string().optional().describe("페이지 번호 (1부터, 기본 1)"),
120
+ };
121
+
122
+ /**
123
+ * `GET /v1/orders` 쿼리 — OpenAPI 문서용 형태(값은 쿼리 문자열). 검증 규칙은 서버가 적용한다:
124
+ * `orderedFrom` 누락 400 `MISSING_PARAMETER`, 날짜 형식 오류 400 `INVALID_PARAMETER`, 31일 초과 400 `RANGE_TOO_WIDE`,
125
+ * `testPayment`가 `true`·`false`가 아니면 400 `INVALID_PARAMETER`
126
+ */
127
+ export const orderListQuerySchema = z.object({
128
+ orderedFrom: z.string().describe("조회 시작 시각 (ISO 8601 날짜 또는 일시, 포함). 필수"),
129
+ orderedTo: z
130
+ .string()
131
+ .optional()
132
+ .describe("조회 끝 시각 (ISO 8601, 포함). 생략하면 orderedFrom부터 31일. 기간은 최대 31일"),
133
+ status: orderItemStatusSchema
134
+ .optional()
135
+ .describe("주문상품 상태 필터 — 이 상태의 주문상품이 하나라도 있는 주문"),
136
+ keyword: z.string().optional().describe("주문번호(일치)·주문자명·수령인명(포함) 검색"),
137
+ testPayment: testPaymentQuery,
138
+ ...pageQuery,
139
+ size: z.string().optional().describe("페이지 크기 (기본 20, 최대 100)"),
140
+ });
141
+
142
+ /**
143
+ * `GET /v1/order-items` 쿼리 — OpenAPI 문서용 형태. `lastChangedFrom` 누락 400 `MISSING_PARAMETER`, 형식 오류 400
144
+ * `INVALID_PARAMETER`, 24시간 초과 400 `RANGE_TOO_WIDE`, `testPayment` 값 오류 400 `INVALID_PARAMETER`
145
+ */
146
+ export const orderItemListQuerySchema = z.object({
147
+ lastChangedFrom: z.string().describe("마지막 변경 시각 조회 시작 (ISO 8601, 포함). 필수"),
148
+ lastChangedTo: z
149
+ .string()
150
+ .optional()
151
+ .describe(
152
+ "마지막 변경 시각 조회 끝 (ISO 8601, 포함). 생략하면 시작부터 24시간. 기간은 최대 24시간",
153
+ ),
154
+ lastChangedType: changeTypeSchema.optional().describe("마지막 변경 유형 필터"),
155
+ testPayment: testPaymentQuery,
156
+ ...pageQuery,
157
+ size: z.string().optional().describe("페이지 크기 (기본 100, 최대 300)"),
158
+ });
159
+
160
+ export interface OrderListParams extends PageParams {
161
+ orderedFrom: string;
162
+ orderedTo?: string;
163
+ status?: z.infer<typeof orderItemStatusSchema>;
164
+ keyword?: string;
165
+ /** 테스트 결제 필터 — `"true"` 테스트 결제만, `"false"` 실결제만, 생략하면 전부 */
166
+ testPayment?: "true" | "false";
167
+ }
168
+
169
+ export interface OrderItemListParams extends PageParams {
170
+ lastChangedFrom: string;
171
+ lastChangedTo?: string;
172
+ lastChangedType?: z.infer<typeof changeTypeSchema>;
173
+ /** 테스트 결제 필터 — `"true"` 테스트 결제 주문만, `"false"` 실결제만, 생략하면 전부 */
174
+ testPayment?: "true" | "false";
175
+ }
176
+
177
+ export const deliveryMethodSchema = z.enum(["COURIER", "DIRECT", "QUICK", "NOTHING"]);
178
+
179
+ export type DeliveryMethod = z.infer<typeof deliveryMethodSchema>;
180
+
181
+ export const dispatchRequestSchema = z
182
+ .object({
183
+ deliveryMethod: deliveryMethodSchema,
184
+ carrierCode: z.string().optional(),
185
+ trackingNumber: z.string().optional(),
186
+ dispatchedAt: z.string().optional(),
187
+ })
188
+ .refine(
189
+ (value) =>
190
+ value.deliveryMethod === "DIRECT" || value.deliveryMethod === "NOTHING"
191
+ ? true
192
+ : !!value.carrierCode && !!value.trackingNumber,
193
+ { message: "COURIER/QUICK 발송은 carrierCode와 trackingNumber가 필수입니다" },
194
+ );
195
+
196
+ export type DispatchRequest = z.infer<typeof dispatchRequestSchema>;
197
+
198
+ export const deliveryInfoSchema = z.object({
199
+ orderItemId: z.string(),
200
+ deliveryMethod: deliveryMethodSchema,
201
+ carrierCode: z.string().nullable(),
202
+ carrierName: z.string().nullable(),
203
+ trackingNumber: z.string().nullable(),
204
+ trackingUrl: z.url().nullable(),
205
+ status: z.enum(["DISPATCHED", "DELIVERING", "DELIVERED"]),
206
+ dispatchedAt: z.string(),
207
+ deliveredAt: z.string().nullable(),
208
+ });
209
+
210
+ export type DeliveryInfo = z.infer<typeof deliveryInfoSchema>;
211
+
212
+ export const carrierSchema = z.object({
213
+ carrierCode: z.string(),
214
+ name: z.string(),
215
+ trackingUrlTemplate: z.string(),
216
+ });
217
+
218
+ export type Carrier = z.infer<typeof carrierSchema>;
219
+
220
+ export const holdOrderItemRequestSchema = z.object({
221
+ reason: z.enum(["OUT_OF_STOCK", "CUSTOMER_REQUEST", "CUSTOMS", "ETC"]),
222
+ detail: z.string().max(500).optional(),
223
+ expectedDispatchDate: z.string(),
224
+ });
225
+
226
+ export type HoldOrderItemRequest = z.infer<typeof holdOrderItemRequestSchema>;
227
+
228
+ export const cancelBySellerRequestSchema = z.object({
229
+ reason: z.enum(["OUT_OF_STOCK", "PRICE_ERROR", "DELIVERY_IMPOSSIBLE", "ETC"]),
230
+ detail: z.string().max(500).optional(),
231
+ });
232
+
233
+ export type CancelBySellerRequest = z.infer<typeof cancelBySellerRequestSchema>;