- 상품에 재고 없는 옵션(optionLabel/options — 예: 키링 색상)을 도입하고 주문 항목에 optionId/optionName 스냅샷 저장 - 주문 생성 시 옵션 검증: 옵션 상품에 미선택이면 OPTION_REQUIRED, 무옵션 상품에 optionId가 오면 INVALID_INPUT - 같은 상품의 색상별 항목을 지원하도록 상품 문서를 productId당 한 번만 읽게 정리 - 재고는 별도 플랫폼에서 관리하므로 서버 재고 개념 전면 제거(ProductDoc 재고 필드, availableStock, 주문 예약/차감, stock/adjust 엔드포인트, order/status restock) - 상세 카탈로그·주문 DTO에 옵션 노출, product/upsert가 optionLabel/options 수용 - 시드/업로드 스크립트의 재고 필드 기록 제거, vitest 계약 테스트 추가
35 lines
1.2 KiB
TypeScript
35 lines
1.2 KiB
TypeScript
import "./_bootstrap";
|
|
import { Timestamp } from "firebase-admin/firestore";
|
|
import { firestore } from "../src/firebase";
|
|
|
|
const products = [
|
|
{ id: "acrylic-keyring", name: "아크릴 키링", pointPrice: 3000, displayOrder: 1 },
|
|
{ id: "magsafe-tok", name: "맥세이프 톡", pointPrice: 6500, displayOrder: 2 },
|
|
{ id: "keyring-doll", name: "키링 인형", pointPrice: 11000, displayOrder: 3 },
|
|
{ id: "crossbag", name: "크로스백", pointPrice: 15000, displayOrder: 4 },
|
|
] as const;
|
|
|
|
async function main() {
|
|
const now = Timestamp.now();
|
|
for (const p of products) {
|
|
const product = firestore.doc(`products/${p.id}`);
|
|
const old = await product.get();
|
|
const existing = old.data();
|
|
const draft = old.exists ? {} : {
|
|
active: false,
|
|
redeemable: false,
|
|
mainImages: [],
|
|
detailImages: [],
|
|
};
|
|
await product.set({
|
|
name: p.name,
|
|
pointPrice: p.pointPrice,
|
|
displayOrder: p.displayOrder,
|
|
...draft,
|
|
createdAt: existing?.createdAt ?? now,
|
|
updatedAt: now,
|
|
}, { merge: true });
|
|
}
|
|
}
|
|
main().then(() => console.log(`seeded ${products.length} reward products`)).catch((e) => { console.error(e); process.exitCode = 1; });
|