feat: enhance survey sales API and component integration

- 조사매물 조회 시 권한 확인 로직 추가
This commit is contained in:
Dayoung 2025-06-02 18:09:42 +09:00
parent c6664e9827
commit e756465250
5 changed files with 83 additions and 29 deletions

View File

@ -1,18 +1,60 @@
import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/libs/prisma'
import { convertToSnakeCase } from '@/utils/common-utils'
import { SessionData } from '@/types/Auth'
type SessionParams = {
role: string | null
storeId: string | null
builderNo: string | null
isLoggedIn: string | null
}
const checkRole = (survey: any, sessionParams: SessionParams) => {
switch (sessionParams.role) {
case 'T01':
return true
case 'Admin':
if (survey.SUBMISSION_STATUS) {
return survey.SUBMISSION_TARGET_ID === sessionParams.storeId
}
return survey.STORE_ID === sessionParams.storeId
case 'Admin_Sub':
if (survey.SUBMISSION_STATUS) {
return survey.SUBMISSION_TARGET_ID === sessionParams.builderNo
}
return survey.STORE_ID === sessionParams.storeId && survey.CONSTRUCTION_POINT_ID === sessionParams.builderNo
case 'Partner':
case 'Builder':
return survey.CONSTRUCTION_POINT_ID === sessionParams.builderNo
default:
return false
}
}
export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
try {
const { id } = await params
const { searchParams } = new URL(request.url)
const sessionParams: SessionParams = {
role: searchParams.get('role'),
storeId: searchParams.get('storeId'),
builderNo: searchParams.get('builderNo'),
isLoggedIn: searchParams.get('isLoggedIn'),
}
// @ts-ignore
const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.findUnique({
where: { ID: Number(id) },
const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.findFirst({
where: {
ID: Number(id),
},
include: {
DETAIL_INFO: true,
},
})
return NextResponse.json(survey)
if (checkRole(survey, sessionParams)) {
return NextResponse.json(survey)
}
} catch (error) {
console.error('Error fetching survey:', error)
return NextResponse.json({ error: 'Failed to fetch survey' }, { status: 500 })

View File

@ -4,16 +4,20 @@ import { useEffect, useState } from 'react'
import { useSurveySaleTabState } from '@/store/surveySaleTabState'
import type { SurveyBasicRequest } from '@/types/Survey'
import type { Mode } from 'fs'
import { useSessionStore } from '@/store/session'
import { usePopupController } from '@/store/popupController'
import { useAddressStore } from '@/store/addressStore'
import { SessionData } from '@/types/Auth'
export default function BasicForm(props: { basicInfo: SurveyBasicRequest; setBasicInfo: (basicInfo: SurveyBasicRequest) => void; mode: Mode }) {
const { basicInfo, setBasicInfo, mode } = props
export default function BasicForm(props: {
basicInfo: SurveyBasicRequest
setBasicInfo: (basicInfo: SurveyBasicRequest) => void
mode: Mode
session: SessionData
}) {
const { basicInfo, setBasicInfo, mode, session } = props
const { setBasicInfoSelected } = useSurveySaleTabState()
const [isFlip, setIsFlip] = useState<boolean>(true)
const { session } = useSessionStore()
const { addressData } = useAddressStore()
useEffect(() => {

View File

@ -32,10 +32,12 @@ export default function ButtonForm(props: {
// --------------------------------------------------------------
// 권한
// 제출권한
// 제출권한 있는 회원
const [isSubmiter, setIsSubmiter] = useState(false)
// 작성자
const [isWriter, setIsWriter] = useState(false)
// 제출받은 대상자
const [isReceiver, setIsReceiver] = useState(false)
const isSubmit = props.data.basic.submissionStatus
useEffect(() => {
@ -44,11 +46,13 @@ export default function ButtonForm(props: {
// T01 제출권한 없음
case 'T01':
setIsSubmiter(false)
setIsReceiver(!props.data.basic.submissionTargetId && !props.data.basic.submissionTargetNm)
break
// 1차 판매점(Order) + 2차 판매점(Musubi) => 같은 판매점 제출권한
case 'Admin':
case 'Admin_Sub':
setIsSubmiter(session.storeNm === props.data.basic.store && session.builderNo === props.data.basic.constructionPointId)
setIsReceiver(session?.storeId === props.data.basic.submissionTargetId)
break
// 시공권한 User(Musubi) + Partner => 같은 시공ID 제출권한
case 'Builder':
@ -59,7 +63,6 @@ export default function ButtonForm(props: {
setIsSubmiter(false)
break
}
setIsWriter(session.userNm === props.data.basic.representative)
}
setSaveData({
@ -175,19 +178,11 @@ export default function ButtonForm(props: {
// ------------------------------------------------------------
// 제출 완료 된 매물의 경우 제출 권한 있으면 수정/삭제 불가능
if (mode === 'READ' && isSubmit && isSubmiter) {
return (
<>
<div className="sale-form-btn-wrap">
<div className="btn-flex-wrap">
<ListButton />
</div>
</div>
</>
)
if (!session?.isLoggedIn) {
return <></>
}
if (mode === 'READ' && session?.role === 'T01' && (!isSubmit || (props.data.basic.submissionTargetId && props.data.basic.submissionTargetNm))) {
if (mode === 'READ' && isSubmit && isSubmiter) {
return (
<>
<div className="sale-form-btn-wrap">
@ -205,8 +200,8 @@ export default function ButtonForm(props: {
<div className="sale-form-btn-wrap">
<div className="btn-flex-wrap">
<ListButton />
<EditButton setMode={setMode} id={id.toString()} mode={mode} />
{(isWriter || !isSubmiter) && <DeleteButton handleDelete={handleDelete} />}
{(isSubmiter || (isReceiver && isSubmit)) && <EditButton setMode={setMode} id={id.toString()} mode={mode} />}
{(isWriter || (isReceiver && isSubmit)) && <DeleteButton handleDelete={handleDelete} />}
{!isSubmit && isSubmiter && <SubmitButton handleSubmit={handleSubmit} />}
</div>
</div>
@ -218,7 +213,7 @@ export default function ButtonForm(props: {
<ListButton />
<TempButton setMode={setMode} handleSave={() => handleSave(true, false)} />
<SaveButton handleSave={() => handleSave(false, false)} />
{session?.role === 'T01' || props.data.basic.submissionStatus ? <></> : <SubmitButton handleSubmit={handleSubmit} />}
{session?.role === 'T01' || isSubmit ? <></> : <SubmitButton handleSubmit={handleSubmit} />}
</div>
</div>
)}

View File

@ -7,6 +7,7 @@ import BasicForm from './BasicForm'
import RoofForm from './RoofForm'
import { useParams, useSearchParams } from 'next/navigation'
import { useSurvey } from '@/hooks/useSurvey'
import { useSessionStore } from '@/store/session'
const roofInfoForm: SurveyDetailRequest = {
contractCapacity: null,
@ -74,6 +75,7 @@ export default function DetailForm() {
const id = Number(routeId) ? Number(routeId) : Number(idParam)
const { surveyDetail, validateSurveyDetail } = useSurvey(Number(id))
const { session } = useSessionStore()
const [mode, setMode] = useState<Mode>(modeset)
const [basicInfoData, setBasicInfoData] = useState<SurveyBasicRequest>(basicInfoForm)
@ -81,7 +83,7 @@ export default function DetailForm() {
useEffect(() => {
if (Number(idParam) !== 0 || surveyDetail === null) {
alert('データが見つかりません。')
alert('権限がありません。')
window.location.href = '/survey-sale'
}
if (surveyDetail && (mode === 'EDIT' || mode === 'READ')) {
@ -94,7 +96,7 @@ export default function DetailForm() {
}
}
}
}, [surveyDetail, id])
}, [surveyDetail, id, mode, session])
const data = {
basic: basicInfoData,
@ -107,7 +109,7 @@ export default function DetailForm() {
<>
<div className="sale-detail-toggle-wrap">
{/* 기본정보 */}
<BasicForm basicInfo={basicInfoData} setBasicInfo={setBasicInfoData} mode={mode} />
<BasicForm basicInfo={basicInfoData} setBasicInfo={setBasicInfoData} mode={mode} session={session} />
{/* 전기/지붕정보 */}
<RoofForm roofInfo={roofInfoData} setRoofInfo={setRoofInfoData} mode={mode} />
<ButtonForm {...buttonFormProps} />

View File

@ -5,6 +5,7 @@ import { useSurveyFilterStore } from '@/store/surveyFilterStore'
import { useSessionStore } from '@/store/session'
import { useAxios } from './useAxios'
import { queryStringFormatter } from '@/utils/common-utils'
import { AxiosError } from 'axios'
export const requiredFields = [
{
@ -111,8 +112,18 @@ export function useSurvey(id?: number): {
queryFn: async () => {
if (id === undefined) throw new Error('id is required')
if (id === null || isNaN(id)) return null
const resp = await axiosInstance(null).get<SurveyBasicInfo>(`/api/survey-sales/${id}`)
return resp.data
if (session?.isLoggedIn) {
const resp = await axiosInstance(null).get<SurveyBasicInfo>(`/api/survey-sales/${id}`, {
params: {
role: session?.role,
storeId: session?.storeId,
builderNo: session?.builderNo,
isLoggedIn: session?.isLoggedIn,
},
})
return resp.data
}
return null
},
enabled: id !== undefined,
})