Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,6 @@ caquick_ddl.sql
src/features/example/*

.figma/

# 지역 시드 원본 CSV (대용량 공공데이터, 파싱 산출 regions.generated.json 만 커밋)
prisma/seed/data/*.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-- AlterTable
ALTER TABLE `store` ADD COLUMN `region_id` BIGINT UNSIGNED NULL;

-- CreateTable
CREATE TABLE `region` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`parent_id` BIGINT UNSIGNED NULL,
`level` TINYINT UNSIGNED NOT NULL,
`name` VARCHAR(80) NOT NULL,
`slug` VARCHAR(120) NOT NULL,
`sort_order` INTEGER NOT NULL DEFAULT 0,
`is_active` BOOLEAN NOT NULL DEFAULT true,
`center_lat` DECIMAL(10, 7) NULL,
`center_lng` DECIMAL(10, 7) NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
`deleted_at` DATETIME(3) NULL,

UNIQUE INDEX `region_slug_key`(`slug`),
INDEX `idx_region_parent_sort`(`parent_id`, `sort_order`),
INDEX `idx_region_level_active`(`level`, `is_active`),
INDEX `idx_region_deleted_at`(`deleted_at`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateIndex
CREATE INDEX `idx_store_region_id` ON `store`(`region_id`);

-- AddForeignKey
ALTER TABLE `region` ADD CONSTRAINT `region_parent_id_fkey` FOREIGN KEY (`parent_id`) REFERENCES `region`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `store` ADD CONSTRAINT `store_region_id_fkey` FOREIGN KEY (`region_id`) REFERENCES `region`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
42 changes: 42 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,43 @@ model AuthRefreshSession {
@@map("auth_refresh_session")
}

/**
* =========================
* Region (지역 마스터)
* - level 1 = 1차 광역그룹 (예: 서울 북부, 경기 남부, 인천)
* - level 2 = 2차 시군구 (예: 강남구, 수원시영통구, 강화군)
* - 동(洞)을 직접 보유한 표준 시군구를 2차로 채택. parent_id로 1차에 귀속.
* =========================
*/

model Region {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
parent_id BigInt? @db.UnsignedBigInt // null = 1차 광역그룹

level Int @db.UnsignedTinyInt
name String @db.VarChar(80)
slug String @unique @db.VarChar(120)
sort_order Int @default(0)
is_active Boolean @default(true) @db.TinyInt

// 현재위치 기반 추천용 중심좌표. 좌표 데이터는 후속 확보 → 초기엔 비어 있을 수 있음
center_lat Decimal? @db.Decimal(10, 7)
center_lng Decimal? @db.Decimal(10, 7)

created_at DateTime @default(now()) @db.DateTime(3)
updated_at DateTime @updatedAt @db.DateTime(3)
deleted_at DateTime? @db.DateTime(3)

parent Region? @relation("RegionTree", fields: [parent_id], references: [id])
children Region[] @relation("RegionTree")
stores Store[]

@@index([parent_id, sort_order], map: "idx_region_parent_sort")
@@index([level, is_active], map: "idx_region_level_active")
@@index([deleted_at], map: "idx_region_deleted_at")
@@map("region")
}

/**
* =========================
* 2) Store
Expand All @@ -297,6 +334,9 @@ model Store {
address_district String? @db.VarChar(80)
address_neighborhood String? @db.VarChar(80)

// 지역 필터용 2차 시군구(Region level 2). 기존 address_* free-text는 표시·역호환 유지
region_id BigInt? @db.UnsignedBigInt

latitude Decimal? @db.Decimal(10, 7)
longitude Decimal? @db.Decimal(10, 7)

Expand All @@ -316,6 +356,7 @@ model Store {
deleted_at DateTime? @db.DateTime(3)

seller_account Account @relation("StoreSellerAccount", fields: [seller_account_id], references: [id])
region Region? @relation(fields: [region_id], references: [id])

business_hours StoreBusinessHour[]
special_closures StoreSpecialClosure[]
Expand All @@ -333,6 +374,7 @@ model Store {
@@index([seller_account_id], map: "idx_store_seller")
@@index([store_name], map: "idx_store_name")
@@index([address_city, address_district, address_neighborhood], map: "idx_store_region")
@@index([region_id], map: "idx_store_region_id")
@@index([deleted_at], map: "idx_store_deleted_at")
@@map("store")
}
Expand Down
4 changes: 4 additions & 0 deletions prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { resetSeedScope } from './seed/idempotent';
import { seedNotifications } from './seed/notifications';
import { seedOrders } from './seed/orders';
import { seedRecentViews } from './seed/recent-views';
import { seedRegions } from './seed/regions';
import { seedReviews } from './seed/reviews';
import { seedSearchHistory } from './seed/search-history';
import { seedStores } from './seed/stores';
Expand All @@ -35,6 +36,9 @@ async function main(): Promise<void> {
log('유저 + 프로필 시드 중...');
const users = await seedUsers(prisma);

log('지역 마스터 시드 중...');
await seedRegions(prisma);

log('매장 + 상품 시드 중...');
const stores = await seedStores(prisma);

Expand Down
Loading
Loading