diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 45a6939..778ea0c 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -13,7 +13,6 @@ model SD_SURVEY_SALES_BASIC_INFO { REPRESENTATIVE String @db.NVarChar(200) STORE String? @db.NVarChar(200) CONSTRUCTION_POINT String? @db.NVarChar(200) - CONSTRUCTION_POINT_ID String? @db.NVarChar(200) INVESTIGATION_DATE String? @db.NVarChar(10) BUILDING_NAME String? @db.NVarChar(200) CUSTOMER_NAME String? @db.NVarChar(200) @@ -23,11 +22,12 @@ model SD_SURVEY_SALES_BASIC_INFO { SUBMISSION_STATUS Boolean @default(false) SUBMISSION_DATE DateTime? @db.Date SUBMISSION_TARGET_ID String? @db.NVarChar(200) - SUBMISSION_TARGET_NM String? @db.NVarChar(200) REG_DT DateTime @default(now()) UPT_DT DateTime @updatedAt REPRESENTATIVE_ID String? @db.NVarChar(100) STORE_ID String? @db.NVarChar(100) + CONSTRUCTION_POINT_ID String? @db.NVarChar(200) + SUBMISSION_TARGET_NM String? @db.NVarChar(200) DETAIL_INFO SD_SURVEY_SALES_DETAIL_INFO? } @@ -179,3 +179,304 @@ model MS_USR_TRK { REG_DT DateTime @default(now()) DATA String? @db.NVarChar(200) } + +model BC_QM_BUILDER { + COMP_CD String @db.NVarChar(4) + BUILDER_NO String @db.NVarChar(50) + AGENCY_STORE_ID String @db.NVarChar(100) + BUILDER_NM String @db.NVarChar(100) + BUILDER_ID String? @db.NVarChar(100) + ZIP_NO String? @db.NVarChar(7) + PRFT_JP String? @db.NVarChar(100) + MNCP_NM String? @db.NVarChar(100) + ADDR_NM String? @db.NVarChar(200) + ADDR_DTL String? @db.NVarChar(200) + RECEIVER_NM String? @db.NVarChar(100) + RECEIVER_CONTACT_NO String? @db.NVarChar(100) + USE_YN String? @db.NVarChar(1) + REG_DT DateTime? @db.DateTime + REG_ID String? @db.NVarChar(50) + UPT_DT DateTime? @db.DateTime + UPT_ID String? @db.NVarChar(50) + BC_QM_USER BC_QM_USER[] + + @@id([COMP_CD, BUILDER_NO], map: "PK_BC_QM_BUILDER") +} + +model BC_QM_TERMS { + COMP_CD String @db.NVarChar(4) + TERMS_NO Decimal @db.Decimal(18, 0) + VER_NO String @db.NVarChar(3) + VER_SUB_NO String @db.NVarChar(3) + OPERTN_DT DateTime @db.Date + TERMS_CTNT String @db.NVarChar(Max) + DEL_YN String? @db.NVarChar(1) + REG_DT DateTime? @db.DateTime + REG_ID String? @db.NVarChar(50) + UPT_DT DateTime? @db.DateTime + UPT_ID String? @db.NVarChar(50) + BC_QM_USER BC_QM_USER[] + + @@id([TERMS_NO, COMP_CD], map: "PK_BC_QM_TERMS") +} + +model BC_QM_USER { + COMP_CD String @db.NVarChar(4) + USER_ID String @db.NVarChar(50) + AGENCY_STORE_ID String @db.NVarChar(100) + USER_NM String @db.NVarChar(100) + USER_AUTH_CD String @db.NVarChar(10) + EMAIL String? @db.NVarChar(100) + PSTN_NM String? @db.NVarChar(100) + TEL_NO String? @db.NVarChar(100) + MOBILE_NO String? @db.NVarChar(100) + FAX_NO String? @db.NVarChar(100) + LAST_LOGIN_DT DateTime? @db.DateTime + PWD String @db.NVarChar(100) + PWD_INIT_YN String? @default("N", map: "DF__BC_QM_USE__PWD_I__42E1EEFE") @db.NVarChar(1) + LOGIN_FAIL_CNT Decimal? @default(0, map: "DF__BC_QM_USE__LOGIN__43D61337") @db.Decimal(18, 0) + LAST_LOGIN_FAIL_DT DateTime? @db.DateTime + LAST_PWD_UPT_DT DateTime? @db.DateTime + BUILDER_NO String? @db.NVarChar(50) + ZIP_NO String? @db.NVarChar(7) + PRFT_JP String? @db.NVarChar(100) + MNCP_NM String? @db.NVarChar(100) + ADDR_NM String? @db.NVarChar(200) + TERMS_AGREE_YN String? @default("N", map: "DF__BC_QM_USE__TERMS__44CA3770") @db.NVarChar(1) + TERMS_AGREE_DT DateTime? @db.DateTime + AGREE_TERMS_NO Decimal? @db.Decimal(18, 0) + STAT_CD String? @db.NVarChar(1) + DEL_YN String? @db.NVarChar(1) + REG_DT DateTime? @db.DateTime + REG_ID String? @db.NVarChar(50) + UPT_DT DateTime? @db.DateTime + UPT_ID String? @db.NVarChar(50) + USER_NM_KANA String? @db.NVarChar(50) + BC_QM_BUILDER BC_QM_BUILDER? @relation(fields: [COMP_CD, BUILDER_NO], references: [COMP_CD, BUILDER_NO], onUpdate: NoAction, map: "FK_BC_QM_USER_01") + BC_QM_TERMS BC_QM_TERMS? @relation(fields: [AGREE_TERMS_NO, COMP_CD], references: [TERMS_NO, COMP_CD], onUpdate: NoAction, map: "FK_BC_QM_USER_02") + + @@id([COMP_CD, USER_ID], map: "PK_BC_QM_USER") +} + +model IF_PERSON_OFFICE_MAPPING { + IF_SEQ Decimal @id(map: "PK_IF_PERSON_OFFICE_MAPPING") @db.Decimal(22, 0) + SEQ Int? + LIFNR String? @db.NVarChar(10) + VKBUR String? @db.NVarChar(4) + IF_DT DateTime? @db.DateTime + IF_STS String? @db.NVarChar(1) + IF_MSG String? @db.NVarChar(200) +} + +model MS_CUST_AGENCY_STOREID { + COMP_CD String @db.NVarChar(4) + STORE_ID String @db.NVarChar(100) + AGENCY_STORE_ID String @db.NVarChar(100) + AGENCY_QCAST_NM String? @db.NVarChar(100) + PLAN_REQ_SUBMIT_YN String? @default("N", map: "DF__MS_CUST_A__PLAN___3B40CD36") @db.NVarChar(1) + DEL_YN String? @default("N", map: "DF__MS_CUST_A__DEL_Y__3C34F16F") @db.NVarChar(1) + REG_DT DateTime? @db.DateTime + REG_ID String? @db.NVarChar(50) + UPT_DT DateTime? @db.DateTime + UPT_ID String? @db.NVarChar(50) + EMAIL String? @db.NVarChar(100) + REMARK String? @db.NVarChar(Max) + BDL_TP_CD String? @db.NVarChar(10) + + @@id([COMP_CD, AGENCY_STORE_ID], map: "PK_MS_CUST_AGENCY_STOREID") +} + +model MS_CUST_H { + COMP_CD String @db.NVarChar(4) + CUST_CD String @db.NVarChar(10) + ACCOUNT_GR String? @db.NVarChar(4) + CUST_NM String? @db.NVarChar(70) + HAUS_NO String? @db.NVarChar(10) + POST_CD String? @db.NVarChar(10) + CITY_CD String? @db.NVarChar(12) + CITY_NM String? @db.NVarChar(40) + COUNTRY_CD String? @db.NVarChar(4) + REGION_CD String? @db.NVarChar(4) + STREET_NM String? @db.NVarChar(60) + STREET_NM2 String? @db.NVarChar(60) + STREET_NM3 String? @db.NVarChar(60) + STREET_NM4 String? @db.NVarChar(60) + STREET_NM5 String? @db.NVarChar(60) + TIME_ZONE String? @db.NVarChar(10) + TRANSP_ZONE String? @db.NVarChar(10) + LANG_CD String? @db.NVarChar(2) + TEL_NO String? @db.NVarChar(30) + TEL_NO_EXT String? @db.NVarChar(10) + MOBILE_NO String? @db.NVarChar(30) + FAX_NO String? @db.NVarChar(30) + FAX_NO_EXT String? @db.NVarChar(10) + EMAIL String? @db.NVarChar(100) + INDUSTRY_CD String? @db.NVarChar(4) + VAT_REG_NO String? @db.NVarChar(20) + LOCAT_NO1 Decimal? @db.Decimal(7, 0) + LOCAT_NO2 Decimal? @db.Decimal(5, 0) + RESI_CD String? @db.NVarChar(4) + UTIL_CD String? @db.NVarChar(4) + MARK_PF String? @db.NVarChar(4) + INVS_CD String? @db.NVarChar(4) + PRMT_CD String? @db.NVarChar(4) + SVC_PR_CD String? @db.NVarChar(4) + ENG_CNSL_CD String? @db.NVarChar(4) + RECON_ACC_CD String? @db.NVarChar(20) + SORT_KEY String? @db.NVarChar(12) + CASH_MGMT_GR String? @db.NVarChar(12) + INTEREST_IND_CD String? @db.NVarChar(12) + TERM_PAY_CD String? @db.NVarChar(12) + PAY_HIST_YN String? @db.NVarChar(2) + DUN_PROC_CD String? @db.NVarChar(4) + DUN_BLOCK_CD String? @db.NVarChar(1) + DUN_LEVEL_CD Decimal? @db.Decimal(1, 0) + POLICY_NO String? @db.NVarChar(20) + INSURED_AMT Decimal? @db.Decimal(13, 3) + VAL_TO_DATE DateTime? @db.Date + DEDUCT_RATE Decimal? @db.Decimal(9, 0) + APPLIED_INSURA Decimal? @db.Decimal(13, 3) + EASY_NO String? @db.NVarChar(20) + APPLY_DATE DateTime? @db.Date + EXPIRE_DATE DateTime? @db.Date + ADD_TXT1 String? @db.NVarChar(400) + ADD_TXT2 String? @db.NVarChar(400) + REF_PS_ID String? @db.NVarChar(20) + CUST_COMP_CD String? @db.NVarChar(4) + CUST_TEXT String? @db.NVarChar(Max) + CUST_GRADE String? @db.NVarChar(2) + INCOME_TAX_NO String? @db.NVarChar(20) + STAT_CD String? @db.NVarChar(2) + REG_DT DateTime? @db.DateTime + REG_ID String? @db.NVarChar(50) + UPT_DT DateTime? @db.DateTime + UPT_ID String? @db.NVarChar(50) + QSP_ACCOUNT_GR String? @db.NVarChar(4) + BDL_TP_CD String? @db.NVarChar(10) + BDL_SUB_TP_CD String? @db.NVarChar(100) + MS_CUST_STOREID MS_CUST_STOREID[] + + @@id([COMP_CD, CUST_CD], map: "PK_MS_CUST_H") +} + +model MS_CUST_PERSON { + SEQ Decimal @db.Decimal(22, 0) + COMP_CD String @db.NVarChar(4) + CUST_CD String @db.NVarChar(10) + EOS_LOGIN_ID String? @db.NVarChar(100) + EOS_PWD String? @db.NVarChar(100) + NAME String? @db.NVarChar(50) + PSTN_NM String? @db.NVarChar(50) + EMAIL String? @db.NVarChar(100) + TEL_NO String? @db.NVarChar(100) + AUTHORITY String @db.NVarChar(1) + DEL_YN String? @default("N", map: "DF__MS_CUST_P__DEL_Y__339FAB6E") @db.NVarChar(1) + LOGIN_DT DateTime? @db.DateTime + PWD_INIT_YN String? @db.NVarChar(1) + LOGIN_FAIL_CNT Decimal? @db.Decimal(18, 0) + REG_DT DateTime? @db.DateTime + REG_ID String? @db.NVarChar(50) + UPT_DT DateTime? @db.DateTime + UPT_ID String? @db.NVarChar(50) + LOGIN_FAIL_DT DateTime? @db.DateTime + PLAN_REQ_AUTH String? @default("N", map: "DF__MS_CUST_P__PLAN___3493CFA7") @db.NVarChar(1) + PRICE_VIEW_STAT_CD String? @default("S", map: "DF__MS_CUST_P__PRICE__3587F3E0") @db.NVarChar(10) + SD_SUBMIT_YN String? @default("N", map: "DF__MS_CUST_P__SD_SU__367C1819") @db.NVarChar(1) + STORE_ID String? @db.NVarChar(100) + USER_NM_KANA String? @db.NVarChar(50) + FAX String? @db.NVarChar(100) + PLAN_MAIL_RCV_YN String? @default("Y", map: "DF__MS_CUST_P__PLAN___37703C52") @db.NVarChar(1) + SD_MAIL_RCV_YN String? @default("Y", map: "DF__MS_CUST_P__SD_MA__3864608B") @db.NVarChar(1) + + @@id([SEQ, COMP_CD, CUST_CD], map: "PK_MS_CUST_PERSON") +} + +model MS_CUST_STOREID { + COMP_CD String @db.NVarChar(4) + STORE_ID String @db.NVarChar(100) + CUST_CD String @db.NVarChar(10) + REPRESENTATIVE_STORE_YN String? @db.NVarChar(1) + SP_MODULE_PRICE_SEQ Decimal? @db.Decimal(20, 0) + SP_MODULE_PRICE_EXP_FR_DT DateTime? @db.Date + SP_MODULE_PRICE_EXP_TO_DT DateTime? @db.Date + SP_BOS_PRICE_SEQ Decimal? @db.Decimal(20, 0) + SP_BOS_PRICE_EXP_FR_DT DateTime? @db.Date + SP_BOS_PRICE_EXP_TO_DT DateTime? @db.Date + PKG_PRICE_RANK String? @default("C", map: "DF__MS_CUST_S__PKG_P__29221CFB") @db.NVarChar(3) + SP_PKG_PRICE Decimal? @db.Decimal(13, 1) + SP_PKG_PRICE_EXP_FR_DT DateTime? @db.Date + SP_PKG_PRICE_EXP_TO_DT DateTime? @db.Date + DEL_YN String? @default("N", map: "DF__MS_CUST_S__DEL_Y__2A164134") @db.NVarChar(1) + REG_DT DateTime? @db.DateTime + REG_ID String? @db.NVarChar(50) + UPT_DT DateTime? @db.DateTime + UPT_ID String? @db.NVarChar(50) + MOVE_DT DateTime? @db.DateTime + MOVE_ID String? @db.NVarChar(50) + STORE_QCAST_NM String? @db.NVarChar(100) + PLAN_REQ_AUTH String? @default("N", map: "DF__MS_CUST_S__PLAN___2B0A656D") @db.NVarChar(1) + PKG_EXCEPT_YN String? @default("N", map: "DF__MS_CUST_S__PKG_E__2BFE89A6") @db.NVarChar(1) + MODULE_PRICE_RANK String? @default("C", map: "DF__MS_CUST_S__MODUL__2CF2ADDF") @db.NVarChar(20) + BOS_PRICE_RANK String? @default("A", map: "DF__MS_CUST_S__BOS_P__2DE6D218") @db.NVarChar(20) + PLAN_REQ_SUBMIT_YN String? @default("N", map: "DF__MS_CUST_S__PLAN___2EDAF651") @db.NVarChar(1) + QSP_SUBAL_YN String? @default("N", map: "DF__MS_CUST_S__QSP_S__2FCF1A8A") @db.NVarChar(1) + MS_CUST_H MS_CUST_H @relation(fields: [COMP_CD, CUST_CD], references: [COMP_CD, CUST_CD], onUpdate: NoAction, map: "MS_CUST_STOREID_FK") + + @@id([COMP_CD, STORE_ID], map: "PK_MS_CUST_STOREID") + @@index([COMP_CD, CUST_CD], map: "IDX_MS_CUST_STOREID_COMP_CD_01") +} + +model MS_CUST_STOREID_ADDITNL { + COMP_CD String @db.NVarChar(20) + STORE_ID String @db.NVarChar(100) + REQ_CUST_CD String? @db.NVarChar(10) + REQ_STORE_QCAST_NM String? @db.NVarChar(100) + STORE_QCAST_NM_KANA String? @db.NVarChar(100) + BIZ_NO String? @db.NVarChar(20) + POST_CD String? @db.NVarChar(10) + ADDR String? @db.NVarChar(255) + TEL_NO String? @db.NVarChar(100) + FAX String? @db.NVarChar(100) + APPR_DT DateTime? @db.DateTime + APPR_ID String? @db.NVarChar(50) + APPR_STAT_CD String? @db.NVarChar(10) + APPR_REMARKS String? @db.NVarChar(300) + REQ_APPR_DT DateTime? @db.DateTime + PAY_TERMS_CD String? @db.NVarChar(10) + FIRST_STORE_ID String? @db.NVarChar(100) + PARENT_STORE_ID String? @db.NVarChar(100) + STORE_LVL Int? + KAM_ID String? @db.NVarChar(50) + QT_COMP_NM String? @db.NVarChar(100) + QT_POST_CD String? @db.NVarChar(10) + QT_ADDR String? @db.NVarChar(255) + QT_TEL_NO String? @db.NVarChar(100) + QT_FAX String? @db.NVarChar(100) + QT_E_MAIL String? @db.NVarChar(100) + ORD_DELI_TARGET String? @db.NVarChar(100) + ORD_DELI_COMP_NM String? @db.NVarChar(100) + ORD_DELI_COMP_USER_NM String? @db.NVarChar(40) + ORD_DELI_TEL_NO String? @db.NVarChar(100) + ORD_DELI_POST_CD String? @db.NVarChar(10) + ORD_DELI_REMARKS String? @db.NVarChar(200) + GUAR_STORE_NM String? @db.NVarChar(100) + GUAR_STORE_POST_CD String? @db.NVarChar(10) + GUAR_STORE_ADDR String? @db.NVarChar(255) + GUAR_TEL_NO String? @db.NVarChar(100) + NORTH_MODULE_YN String? @default("N", map: "DF__MS_CUST_S__NORTH__17036CC0") @db.NVarChar(1) + DEL_YN String? @default("N", map: "DF__MS_CUST_S__DEL_Y__17F790F9") @db.NVarChar(1) + REG_DT DateTime? @db.DateTime + REG_ID String? @db.NVarChar(50) + UPT_DT DateTime? @db.DateTime + UPT_ID String? @db.NVarChar(50) + REQ_MODULE_PRICE_RANK String? @db.NVarChar(20) + REQ_BOS_PRICE_RANK String? @db.NVarChar(20) + REQ_PKG_PRICE_RANK String? @db.NVarChar(3) + REQ_BDL_TP_CD String? @db.NVarChar(10) + REQ_BDL_SUB_TP_CD String? @db.NVarChar(100) + REMARK String? @db.NVarChar(500) + NORTH_MODULE_UPT_DT DateTime? @db.DateTime + NORTH_MODULE_UPT_ID String? @db.NVarChar(50) + + @@id([COMP_CD, STORE_ID], map: "PK_MS_CUST_STOREID_ADDITNL") +} diff --git a/src/app/api/submission/admin-sub/route.ts b/src/app/api/submission/admin-sub/route.ts new file mode 100644 index 0000000..c8c30f3 --- /dev/null +++ b/src/app/api/submission/admin-sub/route.ts @@ -0,0 +1,42 @@ +import { prisma } from '@/libs/prisma' +import { NextRequest, NextResponse } from 'next/server' + +type AdminSubPerson = { + storeId: string + userId: string + eMail: string + authority: string +} +// 2차점이 자신에게 매핑 된 1차 판매점과 관리자 정보 조회 +export async function GET(request: NextRequest) { + try { + const { searchParams } = new URL(request.url) + const id = searchParams.get('id') + + const query = ` + OPEN SYMMETRIC KEY SYMMETRICKEY DECRYPTION BY CERTIFICATE CERTI_QSPJP; + SELECT + MCS.STORE_ID AS targetStoreId + , MCS.STORE_QCAST_NM AS targetStoreNm + , MCP.EOS_LOGIN_ID AS repUserId + , CONVERT(NVARCHAR(100), DecryptByKey(MCP.EMAIL)) AS repUserEmail + , MCP.AUTHORITY AS auth + FROM MS_CUST_STOREID MCS WITH(NOLOCK) + LEFT OUTER JOIN MS_CUST_PERSON MCP WITH(NOLOCK) + ON MCS.COMP_CD = MCP.COMP_CD + AND MCS.STORE_ID = MCP.STORE_ID + AND MCP.DEL_YN = 'N' + WHERE MCS.COMP_CD = '5200' + AND MCS.STORE_ID = (SELECT STORE_ID FROM MS_CUST_AGENCY_STOREID WHERE AGENCY_STORE_ID = '${id}' AND DEL_YN = 'N') + AND MCP.EMAIL IS NOT NULL + AND MCS.DEL_YN = 'N'; + CLOSE SYMMETRIC KEY SYMMETRICKEY; + ` + const suitable: AdminSubPerson[] = await prisma.$queryRawUnsafe(query) + + return NextResponse.json({ message: 'Hello, world!' }) + } catch (error) { + console.error('❌ 데이터 조회 중 오류가 발생했습니다:', error) + return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 }) + } +} diff --git a/src/app/api/submission/admin/route.ts b/src/app/api/submission/admin/route.ts new file mode 100644 index 0000000..0b52031 --- /dev/null +++ b/src/app/api/submission/admin/route.ts @@ -0,0 +1,46 @@ +import { prisma } from '@/libs/prisma' +import { NextRequest, NextResponse } from 'next/server' + +type SuperPerson = { + storeId: string + salesOfficeCd: string + fromEmail: string + toEmail: string +} + +export async function GET(request: NextRequest) { + try { + const { searchParams } = new URL(request.url) + const id = searchParams.get('id') + + const query = ` + OPEN SYMMETRIC KEY SYMMETRICKEY DECRYPTION BY CERTIFICATE CERTI_QSPJP; + SELECT + MCSA.STORE_ID + , BCL.CODE AS SALES_OFFICE_CD + , REF_CHR1 AS FROM_E_MAIL + , REF_CHR2 AS TO_E_MAIL + FROM MS_CUST_STOREID_ADDITNL MCSA WITH(NOLOCK) + LEFT OUTER JOIN IF_PERSON_OFFICE_MAPPING IPOM WITH(NOLOCK) + ON MCSA.KAM_ID = IPOM.LIFNR + AND IF_STS = 'R' + AND VKBUR IS NOT NULL + AND VKBUR != '' + INNER JOIN BC_COMM_L BCL WITH(NOLOCK) + ON BCL.CODE = IPOM.VKBUR + AND BCL.HEAD_CD = '103200' + AND BCL.DEL_YN = 'N' + WHERE MCSA.COMP_CD = '5200' + AND MCSA.STORE_ID = 'A03' + AND MCSA.DEL_YN = 'N' + ; + CLOSE SYMMETRIC KEY SYMMETRICKEY; + ` + const suitable: SuperPerson[] = await prisma.$queryRawUnsafe(query) + + return NextResponse.json({ message: 'Hello, world!' }) + } catch (error) { + console.error('❌ 데이터 조회 중 오류가 발생했습니다:', error) + return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 }) + } +} diff --git a/src/app/api/submission/builder/route.ts b/src/app/api/submission/builder/route.ts new file mode 100644 index 0000000..41c66ce --- /dev/null +++ b/src/app/api/submission/builder/route.ts @@ -0,0 +1,48 @@ +import { prisma } from '@/libs/prisma' +import { SubmitTargetResponse } from '@/types/Survey' +import { NextRequest, NextResponse } from 'next/server' + +type BuilderPerson = { + agencyStoreId: string + userId: string + eMail: string + userAuthCd: string +} + +// 2차점의 시공권한 user가 해당 판매점의 관리자 정보 조회 +// N == 일반유저, S == 수퍼유저, B == 시공권한유저 +export async function GET(request: NextRequest) { + try { + const { searchParams } = new URL(request.url) + const id = searchParams.get('id') + + const query = ` + OPEN SYMMETRIC KEY SYMMETRICKEY DECRYPTION BY CERTIFICATE CERTI_QSPJP; + SELECT + MCAS.AGENCY_STORE_ID AS targetStoreId + , MCAS.AGENCY_QCAST_NM AS targetStoreNm + , BQU.USER_ID AS repUserId + , CONVERT(NVARCHAR(100), DecryptByKey(BQU.EMAIL)) AS repUserEmail + , BQU.USER_AUTH_CD AS auth + FROM MS_CUST_AGENCY_STOREID MCAS WITH(NOLOCK) + LEFT OUTER JOIN BC_QM_USER BQU WITH(NOLOCK) + ON MCAS.COMP_CD = BQU.COMP_CD + AND MCAS.AGENCY_STORE_ID = BQU.AGENCY_STORE_ID + AND MCAS.DEL_YN = 'N' + WHERE MCAS.COMP_CD = '5200' + AND MCAS.AGENCY_STORE_ID = '${id}' + AND BQU.EMAIL IS NOT NULL + AND BQU.USER_AUTH_CD != 'B' + AND MCAS.DEL_YN = 'N'; + CLOSE SYMMETRIC KEY SYMMETRICKEY; + ` + // const suitable: BuilderPerson[] = await prisma.$queryRawUnsafe(query) + + // return NextResponse.json({ message: 'Hello, world!' }) + const data: SubmitTargetResponse[] = await prisma.$queryRawUnsafe(query) + return NextResponse.json(data) + } catch (error) { + console.error('❌ 데이터 조회 중 오류가 발생했습니다:', error) + return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 }) + } +} diff --git a/src/app/api/submission/super/route.ts b/src/app/api/submission/super/route.ts new file mode 100644 index 0000000..6eed5c7 --- /dev/null +++ b/src/app/api/submission/super/route.ts @@ -0,0 +1,39 @@ +import { prisma } from '@/libs/prisma' +import { NextRequest, NextResponse } from 'next/server' + +type SuperPerson = { + storeId: string + userId: string + eMail: string +} + +export async function GET(request: NextRequest) { + try { + const { searchParams } = new URL(request.url) + const id = searchParams.get('id') + + const query = ` + OPEN SYMMETRIC KEY SYMMETRICKEY DECRYPTION BY CERTIFICATE CERTI_QSPJP; + SELECT + MCSA.STORE_ID + , BU.USER_ID + , CONVERT(NVARCHAR(100), DecryptByKey(BU.E_MAIL)) AS E_MAIL + FROM MS_CUST_STOREID_ADDITNL MCSA WITH(NOLOCK) + LEFT OUTER JOIN BC_USER bu WITH(NOLOCK) + ON MCSA.COMP_CD = BU.COMP_CD + AND MCSA.KAM_ID = BU.KAM_ID + AND BU.STAT_CD = 'A' + AND BU.DEL_YN = 'N' + WHERE MCSA.COMP_CD = '5200' + AND MCSA.STORE_ID = 'A03' + AND MCSA.DEL_YN = 'N'; + CLOSE SYMMETRIC KEY SYMMETRICKEY; + ` + const suitable: SuperPerson[] = await prisma.$queryRawUnsafe(query) + + return NextResponse.json({ message: 'Hello, world!' }) + } catch (error) { + console.error('❌ 데이터 조회 중 오류가 발생했습니다:', error) + return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 }) + } +} diff --git a/src/app/api/survey-sales/[id]/route.ts b/src/app/api/survey-sales/[id]/route.ts index d70471a..8d7806c 100644 --- a/src/app/api/survey-sales/[id]/route.ts +++ b/src/app/api/survey-sales/[id]/route.ts @@ -15,6 +15,7 @@ interface SessionParams { storeId: string | null builderId: string | null isLoggedIn: string | null + isPdf: boolean | null } const checkT01Role = (survey: Survey): boolean => survey.SRL_NO !== '一時保存' @@ -74,6 +75,7 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{ storeId: searchParams.get('storeId'), builderId: searchParams.get('builderId'), isLoggedIn: searchParams.get('isLoggedIn'), + isPdf: searchParams.get('isPdf') === 'true' ? true : false, } // @ts-ignore const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.findFirst({ @@ -84,7 +86,7 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{ DETAIL_INFO: true, }, }) - if (checkRole(survey, sessionParams)) { + if (sessionParams.isPdf || checkRole(survey, sessionParams)) { return NextResponse.json(survey) } else { return NextResponse.json({ error: '該当物件の照会権限がありません。' }, { status: 403 }) diff --git a/src/components/pdf/SurveySaleDownloadPdf.tsx b/src/components/pdf/SurveySaleDownloadPdf.tsx index 71d2922..0cda0e1 100644 --- a/src/components/pdf/SurveySaleDownloadPdf.tsx +++ b/src/components/pdf/SurveySaleDownloadPdf.tsx @@ -6,20 +6,27 @@ import { useParams, useRouter } from 'next/navigation' import { useSurvey } from '@/hooks/useSurvey' import { radioEtcData, roofMaterial, selectBoxOptions, supplementaryFacilities } from '../survey-sale/detail/RoofForm' import { useSpinnerStore } from '@/store/spinnerStore' +import { useSessionStore } from '@/store/session' export default function SurveySaleDownloadPdf() { const params = useParams() const id = params.id const router = useRouter() - const { surveyDetail, isLoadingSurveyDetail } = useSurvey(Number(id)) + const { surveyDetail, isLoadingSurveyDetail } = useSurvey(Number(id), true) const { setIsShow } = useSpinnerStore() + const { session } = useSessionStore() const targetRef = useRef(null) const isGeneratedRef = useRef(false) useEffect(() => { - if (isLoadingSurveyDetail || !surveyDetail || isGeneratedRef.current) return + if (isLoadingSurveyDetail || isGeneratedRef.current) return + if (surveyDetail === null) { + alert('データが見つかりません。') + router.replace('/') + return + } isGeneratedRef.current = true handleDownPdf() }, [surveyDetail?.id, isLoadingSurveyDetail]) @@ -48,11 +55,19 @@ export default function SurveySaleDownloadPdf() { }, } - generatePDF(targetRef, options).then(() => { - setIsShow(false) - router.replace(`/survey-sale/${id}`) - alert('PDFの生成が完了しました。 ポップアップウィンドウからダウンロードしてください。') - }) + generatePDF(targetRef, options) + .then(() => { + setIsShow(false) + if (session?.isLoggedIn) { + router.replace(`/survey-sale/${id}`) + } else { + router.replace('/') + } + alert('PDFの生成が完了しました。 ポップアップウィンドウからダウンロードしてください。') + }) + .catch((error: any) => { + console.error('error', error) + }) } return ( diff --git a/src/components/popup/SurveySaleSubmitPopup.tsx b/src/components/popup/SurveySaleSubmitPopup.tsx index e064628..ce6be9e 100644 --- a/src/components/popup/SurveySaleSubmitPopup.tsx +++ b/src/components/popup/SurveySaleSubmitPopup.tsx @@ -15,7 +15,7 @@ interface SubmitFormData { targetNm: string | null sender: string receiver: string[] | string - reference: string | null + reference: string[] | null title: string contents: string | null } @@ -34,7 +34,7 @@ export default function SurveySaleSubmitPopup() { const { setIsShow } = useSpinnerStore() const { getCommCode } = useCommCode() - const { surveyDetail } = useSurvey(Number(routeId)) + const { surveyDetail, getSubmitTarget } = useSurvey(Number(routeId)) const [submitData, setSubmitData] = useState({ saleBase: null, @@ -54,11 +54,25 @@ export default function SurveySaleSubmitPopup() { getCommCode('SALES_OFFICE_CD').then((codes) => { setCommCodeList(codes) }) + } else if (session?.role === 'Builder' || session?.role === 'Admin_Sub') { + getSubmitTarget({ storeId: surveyDetail?.storeId ?? '', role: session?.role ?? '' }).then((data) => { + if (data) { + setSubmitData({ + ...submitData, + targetId: data[0].targetStoreId, + targetNm: data[0].targetStoreNm, + }) + data.length > 1 && + setSubmitData({ + ...submitData, + receiver: data.filter((item) => item.auth === 'S').map((item) => item.repUserEmail), + reference: data.filter((item) => item.auth === 'N').map((item) => item.repUserEmail), + }) + } + }) } setSubmitData({ ...submitData, - targetId: session?.role === 'Builder' ? surveyDetail?.storeId ?? null : null, - targetNm: session?.role === 'Builder' ? surveyDetail?.store ?? null : null, sender: session?.email ?? '', title: '[HANASYS現地調査] 調査物件が提出. (' + surveyDetail?.srlNo + ')', }) diff --git a/src/components/survey-sale/detail/DataTable.tsx b/src/components/survey-sale/detail/DataTable.tsx index 30bfc40..b02392e 100644 --- a/src/components/survey-sale/detail/DataTable.tsx +++ b/src/components/survey-sale/detail/DataTable.tsx @@ -4,15 +4,12 @@ import { useSurvey } from '@/hooks/useSurvey' import { useParams, useRouter } from 'next/navigation' import { useEffect } from 'react' import DetailForm from './DetailForm' -import { useSessionStore } from '@/store/session' export default function DataTable() { const params = useParams() const id = params.id const router = useRouter() - const { session } = useSessionStore() - useEffect(() => { if (Number.isNaN(Number(id))) { alert('間違ったアプローチです。') diff --git a/src/components/survey-sale/detail/DetailForm.tsx b/src/components/survey-sale/detail/DetailForm.tsx index 8fd1ead..503f7b6 100644 --- a/src/components/survey-sale/detail/DetailForm.tsx +++ b/src/components/survey-sale/detail/DetailForm.tsx @@ -74,7 +74,7 @@ export default function DetailForm() { const modeset = Number(routeId) ? 'READ' : idParam ? 'EDIT' : 'CREATE' const id = Number(routeId) ? Number(routeId) : Number(idParam) - const { surveyDetail, isLoadingSurveyDetail, validateSurveyDetail } = useSurvey(Number(id)) + const { surveyDetail, isLoadingSurveyDetail } = useSurvey(Number(id)) const { session } = useSessionStore() const [mode, setMode] = useState(modeset) @@ -103,9 +103,8 @@ export default function DetailForm() { })) }, [session?.isLoggedIn]) - // 설문 데이터 로딩 및 업데이트 useEffect(() => { - if (isLoadingSurveyDetail || !session?.isLoggedIn) return + if (isLoadingSurveyDetail) return if (surveyDetail && (mode === 'EDIT' || mode === 'READ')) { const { id, uptDt, regDt, detailInfo, ...rest } = surveyDetail setBasicInfoData((prev) => ({ @@ -116,12 +115,9 @@ export default function DetailForm() { if (detailInfo) { const { id, uptDt, regDt, basicInfoId, ...rest } = detailInfo setRoofInfoData(rest) - if (validateSurveyDetail(rest).trim() !== '') { - // validation logic here if needed - } } } - }, [mode, session?.isLoggedIn, isLoadingSurveyDetail]) + }, [mode, isLoadingSurveyDetail, surveyDetail]) const data = { basic: basicInfoData, diff --git a/src/components/survey-sale/list/ListTable.tsx b/src/components/survey-sale/list/ListTable.tsx index 50030ac..12088fe 100644 --- a/src/components/survey-sale/list/ListTable.tsx +++ b/src/components/survey-sale/list/ListTable.tsx @@ -27,12 +27,7 @@ export default function ListTable() { }, [pathname]) useEffect(() => { - if (!session.isLoggedIn || isLoadingSurveyList) return - // if ('status' in surveyList && surveyList.status === 403) { - // alert('権限がありません。') - // router.push('/survey-sale') - // return - // } + if (isLoadingSurveyList) return if ('count' in surveyList && surveyList.count > 0) { if (offset > 0) { setHeldSurveyList((prev) => [...prev, ...surveyList.data]) @@ -44,7 +39,7 @@ export default function ListTable() { setHeldSurveyList([]) setHasMore(false) } - }, [surveyList, offset, session.isLoggedIn]) + }, [surveyList, offset, isLoadingSurveyList]) const handleDetailClick = (id: number) => { router.push(`/survey-sale/${id}`) diff --git a/src/hooks/useSurvey.ts b/src/hooks/useSurvey.ts index 20f304c..7fcc6d5 100644 --- a/src/hooks/useSurvey.ts +++ b/src/hooks/useSurvey.ts @@ -1,5 +1,5 @@ -import type { SurveyBasicInfo, SurveyDetailRequest, SurveyRegistRequest } from '@/types/Survey' -import { useMemo, useEffect } from 'react' +import type { SubmitTargetResponse, SurveyBasicInfo, SurveyDetailRequest, SurveyRegistRequest } from '@/types/Survey' +import { useMemo } from 'react' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useSurveyFilterStore } from '@/store/surveyFilterStore' import { useSessionStore } from '@/store/session' @@ -55,7 +55,10 @@ type ZipCode = { kana3: string } -export function useSurvey(id?: number): { +export function useSurvey( + id?: number, + isPdf?: boolean, +): { surveyList: { data: SurveyBasicInfo[]; count: number } | {} surveyDetail: SurveyBasicInfo | null isLoadingSurveyList: boolean @@ -71,6 +74,7 @@ export function useSurvey(id?: number): { validateSurveyDetail: (surveyDetail: SurveyDetailRequest) => string getZipCode: (zipCode: string) => Promise refetchSurveyList: () => void + getSubmitTarget: (params: { storeId: string; role: string }) => Promise } { const queryClient = useQueryClient() const { keyword, searchOption, isMySurvey, sort, offset } = useSurveyFilterStore() @@ -101,6 +105,9 @@ export function useSurvey(id?: number): { return false } } + if (isPdf) { + return true + } alert('ログインしていません。') return false } @@ -113,7 +120,7 @@ export function useSurvey(id?: number): { queryKey: ['survey', 'list', keyword, searchOption, isMySurvey, sort, offset, session?.storeNm, session?.builderId, session?.role], queryFn: async () => { if (!checkSession()) { - router.replace('/') + router.replace('/login') return { data: [], count: 0 } } const resp = await axiosInstance(null).get<{ data: SurveyBasicInfo[]; count: number }>('/api/survey-sales', { @@ -130,7 +137,6 @@ export function useSurvey(id?: number): { }) return resp.data }, - enabled: session?.isLoggedIn, }) const surveyData = useMemo(() => { if (!surveyListData) return { count: 0, data: [] } @@ -143,7 +149,7 @@ export function useSurvey(id?: number): { queryKey: ['survey', id], queryFn: async () => { if (!checkSession()) { - router.replace('/survey-sale') + router.replace('/login') return null } if (id === 0 || id === undefined) return null @@ -154,6 +160,7 @@ export function useSurvey(id?: number): { storeId: session?.storeId, builderId: session?.builderId, isLoggedIn: session?.isLoggedIn, + isPdf: isPdf, }, }) return resp.data @@ -163,7 +170,7 @@ export function useSurvey(id?: number): { return null } }, - enabled: id !== 0 && id !== undefined && session?.isLoggedIn, + enabled: id !== 0 && id !== undefined, }) const { mutateAsync: createSurvey, isPending: isCreatingSurvey } = useMutation({ @@ -278,6 +285,33 @@ export function useSurvey(id?: number): { } } + const getSubmitTarget = async (params: { storeId: string; role: string }): Promise => { + try { + if (!params.storeId) { + alert('販売店IDがありません。') + return null + } + + const endpoints = { + Admin_Sub: `/api/submission/admin-sub?id=${params.storeId}`, + Builder: `/api/submission/builder?id=${params.storeId}`, + } as const + + const endpoint = endpoints[params.role as keyof typeof endpoints] + if (!endpoint) { + alert('権限が間違っています。') + return null + } + + const { data } = await axiosInstance(null).get(endpoint) + return data + } catch (error: any) { + console.error('Failed to fetch submit target:', error) + alert(error.response?.data.error || 'データの取得に失敗しました。') + return null + } + } + return { surveyList: surveyData.data, surveyDetail: surveyDetail as SurveyBasicInfo | null, @@ -293,6 +327,7 @@ export function useSurvey(id?: number): { submitSurvey, validateSurveyDetail, getZipCode, + getSubmitTarget, refetchSurveyList, } } diff --git a/src/types/Survey.ts b/src/types/Survey.ts index 2db1034..7128926 100644 --- a/src/types/Survey.ts +++ b/src/types/Survey.ts @@ -146,3 +146,11 @@ export type SurveyRegistRequest = { } export type Mode = 'CREATE' | 'EDIT' | 'READ' | 'TEMP' // 등록 | 수정 | 상세 | 임시저장 + +export type SubmitTargetResponse = { + targetStoreId: string + targetStoreNm: string + repUserId: string + repUserEmail: string + auth: string +}