diff --git a/prisma/migrations/20250517232921_init/migration.sql b/prisma/migrations/20250517232921_init/migration.sql new file mode 100644 index 0000000..62ea927 --- /dev/null +++ b/prisma/migrations/20250517232921_init/migration.sql @@ -0,0 +1,21 @@ +-- AlterTable +ALTER TABLE `fundings` ADD COLUMN `is_prolongation` BOOLEAN NOT NULL DEFAULT false; + +-- AlterTable +ALTER TABLE `users` ADD COLUMN `is_onboarded` BOOLEAN NOT NULL DEFAULT false; + +-- CreateTable +CREATE TABLE `refresh_tokens` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `token` VARCHAR(512) NOT NULL, + `user_id` INTEGER NOT NULL, + `expires_at` DATETIME(3) NOT NULL, + `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updated_at` DATETIME(3) NOT NULL, + + UNIQUE INDEX `refresh_tokens_token_key`(`token`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- AddForeignKey +ALTER TABLE `refresh_tokens` ADD CONSTRAINT `refresh_tokens_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 02c7ca5..e90b6f9 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -86,6 +86,7 @@ model Funding { fundedMoney Int @map("funded_money") deadlineDate DateTime @map("deadline_date") @db.DateTime(6) photoUrl String @map("photo_url") @db.VarChar(255) + isProlongation Boolean @map("is_prolongation") @default(false) region Region detailAddress String @map("detail_address") @db.VarChar(30) completeDueDate DateTime @map("complete_due_date") @db.DateTime(6) diff --git a/prisma/seed.ts b/prisma/seed.ts index 6029886..dc787cb 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -5,13 +5,27 @@ const prisma = new PrismaClient(); async function main() { const now = new Date(); const hashedPassword = await bcrypt.hash("testpass", 10); - await prisma.user.create({ - data: { - userId: "test", - password: hashedPassword, - region: "SEOUL", - createdAt: new Date(), - }, + await prisma.user.createMany({ + data: [ + { + userId: "test1", + password: hashedPassword, + region: "SEOUL", + createdAt: new Date(), + }, + { + userId: "test2", + password: hashedPassword, + region: "SEOUL", + createdAt: new Date(), + }, + { + userId: "test3", + password: hashedPassword, + region: "SEOUL", + createdAt: new Date(), + }, + ], }); await prisma.funding.createMany({ data: [ @@ -31,6 +45,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "태양으로 물들어", @@ -48,6 +63,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "에너지 쉼터", @@ -65,6 +81,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "태양이 좋아", @@ -82,6 +99,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "인천 태양광 설치", @@ -99,6 +117,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "수원 태양 굿", @@ -116,6 +135,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "울산 햇빛 짱", @@ -133,6 +153,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "태양광으로 절약", @@ -150,6 +171,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "처음하는 써닝", @@ -167,6 +189,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, // 충청도 @@ -186,6 +209,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "충주 태양이양", @@ -203,6 +227,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "해안 태양열 조명", @@ -220,6 +245,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, // 강원도 @@ -239,6 +265,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "태양열로 전기", @@ -256,6 +283,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "에너지 자립", @@ -273,6 +301,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "무안 태양광 필요", @@ -290,6 +319,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "순천만 써닝하자", @@ -307,6 +337,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "익산이 좋아", @@ -324,6 +355,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "벌써 두번째 펀딩", @@ -341,6 +373,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "성산읍 써닝", @@ -358,6 +391,7 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, }, { title: "바람언덕 그린파크", @@ -375,6 +409,679 @@ async function main() { userId: 1, description: "설명", privacyAgreement: true, + isProlongation: false, + }, + { + title: "하수처리장 개선", + description: "신재생에너지 교육과 체험 기회를 제공합니다.", + photoUrl: + "https://cdn.artsnculture.com/news/photo/202012/1303_3034_403.png", + region: "JEJU", + goalMoney: 1245827, + fundedMoney: 939475, + deadlineDate: "2025-07-28T00:00:00.000Z", + detailAddress: "전라남도 여수시", + completeDueDate: "2025-08-26T00:00:00.000Z", + privacyAgreement: true, + status: true, + userId: 1, + isProlongation: false, + }, + { + title: "에코하우스 실증단지", + description: "탄소 배출을 줄이고 자연을 보호합니다.", + photoUrl: + "https://i.pinimg.com/736x/a9/d4/0f/a9d40f8c702693dd30b4f64506719495.jpg", + region: "JEJU", + goalMoney: 1776044, + fundedMoney: 1206311, + deadlineDate: "2025-06-13T00:00:00.000Z", + detailAddress: "부산광역시 해운대구 우동", + completeDueDate: "2025-07-10T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "도심 자가발전 시스템", + description: "탄소 배출을 줄이고 자연을 보호합니다.", + photoUrl: + "https://i.pinimg.com/736x/ea/10/7a/ea107a89475dde645eca72e86046b0e3.jpg", + region: "JEJU", + goalMoney: 1608400, + fundedMoney: 1193095, + deadlineDate: "2025-07-12T00:00:00.000Z", + detailAddress: "충청남도 천안시 동남구", + completeDueDate: "2025-07-18T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "산림지역 전력 설비", + description: "지역 사회의 전력 문제를 해결하는 프로젝트입니다.", + photoUrl: + "https://i.pinimg.com/736x/82/a8/59/82a859369a5f5943c3bd7e86fe66cad8.jpg", + region: "JEJU", + goalMoney: 679420, + fundedMoney: 502332, + deadlineDate: "2025-06-08T00:00:00.000Z", + detailAddress: "강원도 춘천시 석사동", + completeDueDate: "2025-06-16T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "친환경 야시장 전환", + description: "공공시설의 에너지 효율을 향상시킵니다.", + photoUrl: + "https://i.pinimg.com/736x/3b/84/d6/3b84d61ff8bbfe39e16475ad0ff6aca0.jpg", + region: "JEJU", + goalMoney: 871992, + fundedMoney: 863206, + deadlineDate: "2025-07-06T00:00:00.000Z", + detailAddress: "전라남도 여수시", + completeDueDate: "2025-07-14T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "도시 숲 조성", + description: "도심과 농촌의 균형 있는 발전을 추구합니다.", + photoUrl: + "https://i.pinimg.com/736x/a0/a8/39/a0a839884cc97557eb0c533ecba46312.jpg", + region: "JEJU", + goalMoney: 581079, + fundedMoney: 530058, + deadlineDate: "2025-06-21T00:00:00.000Z", + detailAddress: "광주광역시 북구 운암동", + completeDueDate: "2025-06-29T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "농가 에너지 지원", + description: "지역 사회의 전력 문제를 해결하는 프로젝트입니다.", + photoUrl: + "https://i.pinimg.com/736x/a4/65/14/a4651460a4bf9bae49abbf66b23e940f.jpg", + region: "SEOUL", + goalMoney: 1363036, + fundedMoney: 1210175, + deadlineDate: "2025-06-24T00:00:00.000Z", + detailAddress: "전라북도 전주시 완산구", + completeDueDate: "2025-06-26T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "지속가능 커뮤니티 에너지", + description: "신재생에너지 교육과 체험 기회를 제공합니다.", + photoUrl: + "https://i.pinimg.com/736x/3b/84/d6/3b84d61ff8bbfe39e16475ad0ff6aca0.jpg", + region: "SEOUL", + goalMoney: 1722675, + fundedMoney: 1325414, + deadlineDate: "2025-06-11T00:00:00.000Z", + detailAddress: "세종특별자치시 조치원읍", + completeDueDate: "2025-07-03T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "공공시설 태양광", + description: "신재생에너지 교육과 체험 기회를 제공합니다.", + photoUrl: + "https://i.pinimg.com/736x/44/81/8f/44818f19c090311cd3cd652be4c79cf6.jpg", + region: "SEOUL", + goalMoney: 978342, + fundedMoney: 527500, + deadlineDate: "2025-07-01T00:00:00.000Z", + detailAddress: "전라남도 여수시", + completeDueDate: "2025-07-27T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "방범용 조명 개선", + description: "도심과 농촌의 균형 있는 발전을 추구합니다.", + photoUrl: + "https://i.pinimg.com/736x/15/82/ac/1582ac9b9c1a76c95330fe45ea390e33.jpg", + region: "SEOUL", + goalMoney: 1745721, + fundedMoney: 1033072, + deadlineDate: "2025-06-11T00:00:00.000Z", + detailAddress: "경기도 수원시 팔달구", + completeDueDate: "2025-07-10T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "저탄소 도시 실현", + description: "아이들을 위한 깨끗하고 안전한 환경 조성.", + photoUrl: + "https://i.pinimg.com/736x/cb/d0/65/cbd0658916cd4700cbfccf6b5ec9f5da.jpg", + region: "SEOUL", + goalMoney: 1971278, + fundedMoney: 739121, + deadlineDate: "2025-06-07T00:00:00.000Z", + detailAddress: "부산광역시 해운대구 우동", + completeDueDate: "2025-07-06T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "지하철 에너지 효율화", + description: "지속 가능한 에너지로 미래를 밝힙니다.", + photoUrl: + "https://i.pinimg.com/736x/36/2d/2a/362d2a4dac3d2856e854717993e08d64.jpg", + region: "SEOUL", + goalMoney: 1886880, + fundedMoney: 414351, + deadlineDate: "2025-06-04T00:00:00.000Z", + detailAddress: "대구광역시 달서구 본동", + completeDueDate: "2025-06-08T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "도심지 전력 효율화", + description: "지역 사회의 전력 문제를 해결하는 프로젝트입니다.", + photoUrl: + "https://i.pinimg.com/736x/3f/d9/72/3fd972185445334a5ac966af130be17b.jpg", + region: "INCHEON_GYEONGGI", + goalMoney: 1274854, + fundedMoney: 719745, + deadlineDate: "2025-06-08T00:00:00.000Z", + detailAddress: "세종특별자치시 조치원읍", + completeDueDate: "2025-06-14T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "친환경 공장 시범단지", + description: "아이들을 위한 깨끗하고 안전한 환경 조성.", + photoUrl: + "https://i.pinimg.com/736x/ea/10/7a/ea107a89475dde645eca72e86046b0e3.jpg", + region: "INCHEON_GYEONGGI", + goalMoney: 1368934, + fundedMoney: 1124202, + deadlineDate: "2025-06-28T00:00:00.000Z", + detailAddress: "광주광역시 북구 운암동", + completeDueDate: "2025-07-18T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "농촌 마을 공동 태양광", + description: "아이들을 위한 깨끗하고 안전한 환경 조성.", + photoUrl: + "https://i.pinimg.com/736x/7e/7c/8c/7e7c8cc3d103c57d092287218c4c00a9.jpg", + region: "INCHEON_GYEONGGI", + goalMoney: 1695838, + fundedMoney: 371250, + deadlineDate: "2025-07-06T00:00:00.000Z", + detailAddress: "인천광역시 연수구 송도동", + completeDueDate: "2025-07-10T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "전통가옥 태양광 시스템", + description: "아이들을 위한 깨끗하고 안전한 환경 조성.", + photoUrl: + "https://i.pinimg.com/736x/ea/b7/4c/eab74cd5d7a788083c89825ce7fd85f0.jpg", + region: "INCHEON_GYEONGGI", + goalMoney: 1808883, + fundedMoney: 1085314, + deadlineDate: "2025-07-21T00:00:00.000Z", + detailAddress: "충청북도 청주시 상당구", + completeDueDate: "2025-08-10T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "탄소중립 마을 조성", + description: "친환경적인 삶을 위한 첫걸음을 함께해요.", + photoUrl: + "https://i.pinimg.com/736x/0b/a8/da/0ba8da2012d94b35619799f6fa903051.jpg", + region: "INCHEON_GYEONGGI", + goalMoney: 1646333, + fundedMoney: 387636, + deadlineDate: "2025-07-03T00:00:00.000Z", + detailAddress: "울산광역시 남구 삼산동", + completeDueDate: "2025-07-04T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "농촌 마을 전기개선", + description: "재생에너지 기반의 지속가능한 모델 구현.", + photoUrl: + "https://i.pinimg.com/736x/a6/d7/84/a6d7845642f72286445f869df7053d86.jpg", + region: "INCHEON_GYEONGGI", + goalMoney: 1428634, + fundedMoney: 870451, + deadlineDate: "2025-07-22T00:00:00.000Z", + detailAddress: "경상북도 포항시 북구", + completeDueDate: "2025-08-13T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "공원 내 에너지 절감", + description: "지역 주민의 삶의 질을 높이는 전력 개선 사업.", + photoUrl: + "https://i.pinimg.com/736x/fb/c5/46/fbc546003875f689a6d67a8977891e5c.jpg", + region: "GYEONGSANG", + goalMoney: 1914130, + fundedMoney: 1658304, + deadlineDate: "2025-06-08T00:00:00.000Z", + detailAddress: "강원도 춘천시 석사동", + completeDueDate: "2025-06-23T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "지방 도시 태양광 설치", + description: "지속 가능한 에너지로 미래를 밝힙니다.", + photoUrl: + "https://i.pinimg.com/736x/3e/51/cb/3e51cb1e3dd26675f08208b85f104e3f.jpg", + region: "GYEONGSANG", + goalMoney: 1788777, + fundedMoney: 1433087, + deadlineDate: "2025-07-17T00:00:00.000Z", + detailAddress: "경상남도 창원시 성산구", + completeDueDate: "2025-08-07T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "에너지 절약 LED 교체", + description: "지역 주민의 삶의 질을 높이는 전력 개선 사업.", + photoUrl: + "https://i.pinimg.com/736x/49/51/f6/4951f68a4baa890f1d6536146cf4cd0b.jpg", + region: "GYEONGSANG", + goalMoney: 913389, + fundedMoney: 375209, + deadlineDate: "2025-06-30T00:00:00.000Z", + detailAddress: "대전광역시 서구 둔산동", + completeDueDate: "2025-07-25T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "마을 태양광 전환", + description: "기후 위기에 대응하는 스마트 솔루션입니다.", + photoUrl: + "https://i.pinimg.com/736x/a9/24/92/a92492c6e05ab39140a4dae3e9898d82.jpg", + region: "GYEONGSANG", + goalMoney: 1768005, + fundedMoney: 520414, + deadlineDate: "2025-06-29T00:00:00.000Z", + detailAddress: "경상북도 포항시 북구", + completeDueDate: "2025-07-09T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "태양광 벤치 설치", + description: "아이들을 위한 깨끗하고 안전한 환경 조성.", + photoUrl: + "https://i.pinimg.com/736x/a9/24/92/a92492c6e05ab39140a4dae3e9898d82.jpg", + region: "GYEONGSANG", + goalMoney: 1350017, + fundedMoney: 676636, + deadlineDate: "2025-07-26T00:00:00.000Z", + detailAddress: "충청북도 청주시 상당구", + completeDueDate: "2025-08-06T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "하천 정비 태양광 등", + description: "공공시설의 에너지 효율을 향상시킵니다.", + photoUrl: + "https://i.pinimg.com/736x/a6/46/af/a646af907b62001b13cfb993166bcc3b.jpg", + region: "GYEONGSANG", + goalMoney: 1639684, + fundedMoney: 701717, + deadlineDate: "2025-07-23T00:00:00.000Z", + detailAddress: "세종특별자치시 조치원읍", + completeDueDate: "2025-07-26T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "풍력 발전 실험단지", + description: "재생에너지 기반의 지속가능한 모델 구현.", + photoUrl: + "https://i.pinimg.com/736x/16/85/fc/1685fccf593bb334ad5778471f39246a.jpg", + region: "CHUNGCHEONG", + goalMoney: 1087006, + fundedMoney: 1019532, + deadlineDate: "2025-06-26T00:00:00.000Z", + detailAddress: "인천광역시 연수구 송도동", + completeDueDate: "2025-07-04T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "학교 옥상 태양광 설치", + description: "기후 위기에 대응하는 스마트 솔루션입니다.", + photoUrl: + "https://i.pinimg.com/736x/16/85/fc/1685fccf593bb334ad5778471f39246a.jpg", + region: "CHUNGCHEONG", + goalMoney: 1226522, + fundedMoney: 1070533, + deadlineDate: "2025-06-18T00:00:00.000Z", + detailAddress: "강원도 춘천시 석사동", + completeDueDate: "2025-07-18T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "수자원 정화 시스템", + description: "신재생에너지 교육과 체험 기회를 제공합니다.", + photoUrl: + "https://i.pinimg.com/736x/64/cc/72/64cc723abfb0e0987e1c1f53f22cff7a.jpg", + region: "CHUNGCHEONG", + goalMoney: 1911461, + fundedMoney: 678274, + deadlineDate: "2025-07-22T00:00:00.000Z", + detailAddress: "강원도 춘천시 석사동", + completeDueDate: "2025-08-04T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "전기차 충전소 설치", + description: "지속 가능한 에너지로 미래를 밝힙니다.", + photoUrl: + "https://i.pinimg.com/736x/54/f4/ef/54f4efa09160b7f4d26bd76a83e5df0b.jpg", + region: "CHUNGCHEONG", + goalMoney: 1644455, + fundedMoney: 684937, + deadlineDate: "2025-07-31T00:00:00.000Z", + detailAddress: "강원도 춘천시 석사동", + completeDueDate: "2025-08-17T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "학교용 태양광 키트", + description: "탄소 배출을 줄이고 자연을 보호합니다.", + photoUrl: + "https://i.pinimg.com/736x/27/56/43/27564375ce3e2738c1a2bda5e630500c.jpg", + region: "CHUNGCHEONG", + goalMoney: 921331, + fundedMoney: 434193, + deadlineDate: "2025-07-23T00:00:00.000Z", + detailAddress: "충청남도 천안시 동남구", + completeDueDate: "2025-08-12T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "자연보호 캠페인 지원", + description: "전기 소외 지역에 밝은 빛을 선물합니다.", + photoUrl: + "https://i.pinimg.com/736x/15/82/ac/1582ac9b9c1a76c95330fe45ea390e33.jpg", + region: "CHUNGCHEONG", + goalMoney: 592928, + fundedMoney: 419715, + deadlineDate: "2025-07-02T00:00:00.000Z", + detailAddress: "대전광역시 서구 둔산동", + completeDueDate: "2025-08-01T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "주택 태양광 설치", + description: "지역 주민의 삶의 질을 높이는 전력 개선 사업.", + photoUrl: + "https://cdn.artsnculture.com/news/photo/202012/1303_3034_403.png", + region: "GANGWON", + goalMoney: 989809, + fundedMoney: 315988, + deadlineDate: "2025-07-29T00:00:00.000Z", + detailAddress: "서울특별시 영등포구 여의도동", + completeDueDate: "2025-08-12T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "태양광 정원등 프로젝트", + description: "재생에너지 기반의 지속가능한 모델 구현.", + photoUrl: + "https://cdn.artsnculture.com/news/photo/202012/1303_3034_403.png", + region: "GANGWON", + goalMoney: 1845171, + fundedMoney: 1225614, + deadlineDate: "2025-06-06T00:00:00.000Z", + detailAddress: "광주광역시 북구 운암동", + completeDueDate: "2025-06-16T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "폐광지역 재생 프로젝트", + description: "기후 위기에 대응하는 스마트 솔루션입니다.", + photoUrl: + "https://i.pinimg.com/736x/1e/62/26/1e6226a94c8754dce44d44e1ba54a36f.jpg", + region: "GANGWON", + goalMoney: 904012, + fundedMoney: 661611, + deadlineDate: "2025-06-06T00:00:00.000Z", + detailAddress: "전라북도 전주시 완산구", + completeDueDate: "2025-06-25T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "소외지역 태양광 보급", + description: "전기 소외 지역에 밝은 빛을 선물합니다.", + photoUrl: + "https://cdn.electimes.com/news/photo/202412/348273_553312_4712.jpeg", + region: "GANGWON", + goalMoney: 1770378, + fundedMoney: 387470, + deadlineDate: "2025-07-09T00:00:00.000Z", + detailAddress: "광주광역시 북구 운암동", + completeDueDate: "2025-08-08T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "공공기관 태양광 시스템", + description: "지역 사회의 전력 문제를 해결하는 프로젝트입니다.", + photoUrl: + "https://www.energydaily.co.kr/news/photo/202206/128520_82917_4540.jpg", + region: "GANGWON", + goalMoney: 1879914, + fundedMoney: 940797, + deadlineDate: "2025-06-11T00:00:00.000Z", + detailAddress: "광주광역시 북구 운암동", + completeDueDate: "2025-06-19T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "저소득층 전력지원", + description: "공공시설의 에너지 효율을 향상시킵니다.", + photoUrl: + "https://kr.news.cn/20241028/da3ec9e2c87643f19dd1fcd6b6c0d536/20241028da3ec9e2c87643f19dd1fcd6b6c0d536_20241028777c62667e944874af65559430cca682.jpg", + region: "GANGWON", + goalMoney: 971442, + fundedMoney: 459519, + deadlineDate: "2025-06-14T00:00:00.000Z", + detailAddress: "경상북도 포항시 북구", + completeDueDate: "2025-07-14T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "문화재 보호 전력 시스템", + description: "기후 위기에 대응하는 스마트 솔루션입니다.", + photoUrl: + "https://miro.medium.com/v2/resize:fit:1128/format:webp/0*pel80_ucNG_z_CAc.jpg", + region: "JEOLLA", + goalMoney: 1040462, + fundedMoney: 406654, + deadlineDate: "2025-06-05T00:00:00.000Z", + detailAddress: "전라북도 전주시 완산구", + completeDueDate: "2025-06-10T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "산촌 마을 전력 자립", + description: "도심과 농촌의 균형 있는 발전을 추구합니다.", + photoUrl: + "https://miro.medium.com/v2/resize:fit:1128/format:webp/0*pel80_ucNG_z_CAc.jpg", + region: "JEOLLA", + goalMoney: 1064511, + fundedMoney: 563016, + deadlineDate: "2025-07-01T00:00:00.000Z", + detailAddress: "인천광역시 연수구 송도동", + completeDueDate: "2025-07-21T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "기후대응형 태양광", + description: "전기 소외 지역에 밝은 빛을 선물합니다.", + photoUrl: + "https://i.pinimg.com/736x/a9/d4/0f/a9d40f8c702693dd30b4f64506719495.jpg", + region: "JEOLLA", + goalMoney: 1590108, + fundedMoney: 797790, + deadlineDate: "2025-06-17T00:00:00.000Z", + detailAddress: "대구광역시 달서구 본동", + completeDueDate: "2025-06-19T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "전통시장 전기 개선", + description: "탄소 배출을 줄이고 자연을 보호합니다.", + photoUrl: + "https://i.pinimg.com/736x/1e/62/26/1e6226a94c8754dce44d44e1ba54a36f.jpg", + region: "JEOLLA", + goalMoney: 616129, + fundedMoney: 541982, + deadlineDate: "2025-07-02T00:00:00.000Z", + detailAddress: "인천광역시 연수구 송도동", + completeDueDate: "2025-07-13T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "문화시설 태양광 도입", + description: "아이들을 위한 깨끗하고 안전한 환경 조성.", + photoUrl: + "https://i.pinimg.com/736x/01/a9/f0/01a9f01df66507381405556a9e18e0db.jpg", + region: "JEOLLA", + goalMoney: 551105, + fundedMoney: 311703, + deadlineDate: "2025-06-09T00:00:00.000Z", + detailAddress: "세종특별자치시 조치원읍", + completeDueDate: "2025-06-18T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, + }, + { + title: "해변가 쓰레기 정화", + description: "기후 위기에 대응하는 스마트 솔루션입니다.", + photoUrl: + "https://cdn.artsnculture.com/news/photo/202012/1303_3034_403.png", + region: "JEOLLA", + goalMoney: 877687, + fundedMoney: 494145, + deadlineDate: "2025-07-19T00:00:00.000Z", + detailAddress: "전라남도 여수시", + completeDueDate: "2025-08-03T00:00:00.000Z", + isProlongation: false, + privacyAgreement: true, + status: true, + userId: 1, }, ], skipDuplicates: true, // optional: 중복 방지 diff --git a/src/controllers/funding.controller.ts b/src/controllers/funding.controller.ts index 714316d..a8a0ad5 100644 --- a/src/controllers/funding.controller.ts +++ b/src/controllers/funding.controller.ts @@ -287,7 +287,7 @@ export const donateFundingController = async ( next: NextFunction ): Promise => { // 반환 타입 명시 try { - const fundingId = parseInt(req.params.id); + const fundingId = parseInt(req.params.fundingId); const userId = req.user!.id; // authenticateToken 미들웨어에서 설정된 사용자 ID const { userFundedMoney } = req.body; @@ -308,7 +308,7 @@ export const donateFundingController = async ( ); res.sendSuccess( StatusCodes.OK, - "성공적으로 후원하였습니다.", + "후원이 성공적으로 완료되었습니다.", result ); // 성공 시에도 명시적으로 반환하지 않음 (sendSuccess가 응답을 종료) diff --git a/src/repositories/funding.repository.ts b/src/repositories/funding.repository.ts index 6d677f0..48299f9 100644 --- a/src/repositories/funding.repository.ts +++ b/src/repositories/funding.repository.ts @@ -57,44 +57,49 @@ export const findAllFundings = async ( where, orderBy, include: { - user: { // 펀딩 생성자 정보 + user: { + // 펀딩 생성자 정보 select: { userId: true, region: true, - } - }, - userFundings: { // 해당 펀딩에 참여한 사용자들의 후원 정보 + }, + }, + userFundings: { + // 해당 펀딩에 참여한 사용자들의 후원 정보 select: { userId: true, userFundedMoney: true, user: { select: { userId: true, // 후원한 사용자의 ID - } - } - } + }, + }, + }, }, - comments: { // 해당 펀딩의 댓글 정보 + comments: { + // 해당 펀딩의 댓글 정보 select: { content: true, createdAt: true, user: { select: { userId: true, // 댓글 작성자 ID - } - } + }, + }, }, orderBy: { - createdAt: 'desc' // 최신 댓글 순 - } - } + createdAt: "desc", // 최신 댓글 순 + }, + }, }, }); return fundings; }; // 특정 사용자의 펀딩 조회 -export const findFundingsByUserId = async (userId: number): Promise => { +export const findFundingsByUserId = async ( + userId: number +): Promise => { const fundings = await prisma.funding.findMany({ where: { userId }, include: { @@ -102,7 +107,7 @@ export const findFundingsByUserId = async (userId: number): Promise = select: { userId: true, region: true, - } + }, }, userFundings: { select: { @@ -111,9 +116,9 @@ export const findFundingsByUserId = async (userId: number): Promise = user: { select: { userId: true, - } - } - } + }, + }, + }, }, comments: { select: { @@ -122,13 +127,13 @@ export const findFundingsByUserId = async (userId: number): Promise = user: { select: { userId: true, - } - } + }, + }, }, orderBy: { - createdAt: 'desc' - } - } + createdAt: "desc", + }, + }, }, }); return fundings; @@ -166,6 +171,18 @@ export const fundingDonate = async ( ): Promise<{ funding: Funding; userFunding: any }> => { // 트랜잭션으로 처리 return await prisma.$transaction(async (tx) => { + const fundingAuthor = await tx.funding.findUnique({ + where: { id: fundingId }, + select: { userId: true }, + }); + // 펀딩이 존재하지 않으면 예외 + if (!fundingAuthor) { + throw new Error("존재하지 않는 펀딩입니다."); + } + // ✅ 1. 작성자와 후원자 동일 여부 체크 + if (fundingAuthor.userId === userId) { + throw new Error("자신이 생성한 펀딩에는 후원할 수 없습니다."); + } // 1. 기존 user_funding 조회 const existingUserFunding = await tx.userFunding.findFirst({ where: { @@ -175,13 +192,14 @@ export const fundingDonate = async ( }); let newUserFundedMoney: bigint; - + // 2. UserFunding 업데이트 또는 생성 let userFunding; if (existingUserFunding) { // 기존 후원 금액에 새로운 금액 추가 - newUserFundedMoney = existingUserFunding.userFundedMoney + userFundedMoney; - + newUserFundedMoney = + existingUserFunding.userFundedMoney + userFundedMoney; + userFunding = await tx.userFunding.update({ where: { id: existingUserFunding.id }, data: { userFundedMoney: newUserFundedMoney }, @@ -189,7 +207,7 @@ export const fundingDonate = async ( } else { // 새 후원 등록 newUserFundedMoney = userFundedMoney; - + userFunding = await tx.userFunding.create({ data: { userId, @@ -214,41 +232,47 @@ export const fundingDonate = async ( }; // 사용자가 참여한 펀딩 목록 조회 -export const findParticipatedFundingsByUserId = async (userId: number): Promise => { +export const findParticipatedFundingsByUserId = async ( + userId: number +): Promise => { const userFundings = await prisma.userFunding.findMany({ where: { userId }, include: { - funding: { // Funding 정보 포함 - include: { // Funding 상세 정보 내 추가 정보 포함 - user: { // 펀딩 생성자 정보 + funding: { + // Funding 정보 포함 + include: { + // Funding 상세 정보 내 추가 정보 포함 + user: { + // 펀딩 생성자 정보 select: { userId: true, region: true, - } + }, }, - comments: { // 해당 펀딩의 댓글 정보 + comments: { + // 해당 펀딩의 댓글 정보 select: { content: true, createdAt: true, user: { select: { userId: true, // 댓글 작성자 ID - } - } + }, + }, }, orderBy: { - createdAt: 'desc' // 최신 댓글 순 - } - } - } + createdAt: "desc", // 최신 댓글 순 + }, + }, + }, }, }, orderBy: { - createdAt: 'desc', // 최신순으로 정렬하거나 필요에 따라 변경 + createdAt: "desc", // 최신순으로 정렬하거나 필요에 따라 변경 }, }); - return userFundings.map(uf => ({ + return userFundings.map((uf) => ({ ...uf.funding, // Funding의 모든 필드 (user, comments 포함) userFundedMoney: uf.userFundedMoney, // 사용자가 해당 펀딩에 후원한 금액 // userFundings 필드는 이미 uf.funding 내에 포함되어 있을 수 있으나, diff --git a/src/routes/funding.ts b/src/routes/funding.ts index 3a09b1c..cd25ca2 100644 --- a/src/routes/funding.ts +++ b/src/routes/funding.ts @@ -35,6 +35,6 @@ router.patch("/:fundingId/prolongation", authenticateToken, prolongFundingHandle router.patch("/:fundingId/close", authenticateToken, closeFundingHandler); // 후원하기 -router.post("/:id/donate", authenticateToken, donateFundingController); +router.patch("/:fundingId/donate", authenticateToken, donateFundingController); export default router; \ No newline at end of file diff --git a/src/services/funding.service.ts b/src/services/funding.service.ts index 55ababe..2c7978e 100644 --- a/src/services/funding.service.ts +++ b/src/services/funding.service.ts @@ -90,6 +90,8 @@ export const getFundingById = async (id: number): Promise => { throw new Error("펀딩을 찾을 수 없습니다."); } + const funderCount = funding.userFundings ? funding.userFundings.length : 0; + return { fundingId: funding.id, title: funding.title, @@ -100,11 +102,13 @@ export const getFundingById = async (id: number): Promise => { goalMoney: funding.goalMoney, fundedMoney: funding.fundedMoney, achievementRate: funding.goalMoney > 0 ? Math.floor((funding.fundedMoney * 100) / Number(funding.goalMoney)) : 0, + funderCount, deadlineDate: funding.deadlineDate, completeDueDate: funding.completeDueDate, isOpen: funding.status, // status를 isOpen으로 변경 createdAt: funding.createdAt, updatedAt: funding.updatedAt, + userId: funding.userId, }; }; @@ -197,10 +201,10 @@ export const donateFunding = async ( } const result = await fundingDonate(fundingId, userId, userFundedMoney); return { - funding_id: result.funding.id, - user_id: userId, - new_user_funded_money: result.userFunding.userFundedMoney, - updated_funding_total: result.funding.fundedMoney, + fundingId: result.funding.id, + userId: userId, + newUserFundedMoney: result.userFunding.userFundedMoney, + updatedFundingTotal: result.funding.fundedMoney, }; };