chore: enhance survey detail validation

- 건축연수, 단열재의 유무 필드 기타 항목 유효성 검사 추가
- ORDER, MUSUBI 조사매물 목록 검색조건에 판매점Id, 시공점Id 추가
- T01 계정의 경우 제출받은 매물만 수정/삭제 가능하도록 수정
-
This commit is contained in:
Dayoung 2025-06-02 15:46:07 +09:00
parent 1bba8b1af0
commit 1bddc86bcf
9 changed files with 56 additions and 43 deletions

View File

@ -5,8 +5,8 @@ NEXT_PUBLIC_RUN_MODE=development
NEXT_PUBLIC_API_URL=http://localhost:3000
#qsp 로그인 api
# NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120
NEXT_PUBLIC_QSP_API_URL=https://jp-dev.qsalesplatform.com
NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120
# NEXT_PUBLIC_QSP_API_URL=https://jp-dev.qsalesplatform.com
#1:1문의 api
NEXT_PUBLIC_INQUIRY_API_URL=https://jp-dev.qsalesplatform.com

View File

@ -5,8 +5,8 @@ NEXT_PUBLIC_RUN_MODE=local
NEXT_PUBLIC_API_URL=http://localhost:3000
#qsp 로그인 api
# NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120
NEXT_PUBLIC_QSP_API_URL=https://jp-dev.qsalesplatform.com
NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120
# NEXT_PUBLIC_QSP_API_URL=https://jp-dev.qsalesplatform.com
#1:1문의 api
NEXT_PUBLIC_INQUIRY_API_URL=https://jp-dev.qsalesplatform.com

View File

@ -25,8 +25,10 @@ type WhereCondition = {
const SEARCH_OPTIONS = [
'BUILDING_NAME', // 건물명
'REPRESENTATIVE', // 담당자
'STORE', // 판매점
'CONSTRUCTION_POINT', // 시공점
'STORE', // 판매점명
'STORE_ID', // 판매점ID
'CONSTRUCTION_POINT', // 시공점명
'CONSTRUCTION_POINT_ID', // 시공점ID
'CUSTOMER_NAME', // 고객명
'POST_CODE', // 우편번호
'ADDRESS', // 주소

View File

@ -96,6 +96,7 @@ export default function SurveySaleSubmitPopup() {
return true
}
// TODO: Admin_Sub 계정 매핑된 submit target id 추가!!!! && 메일 테스트트
const handleSubmit = () => {
if (validateData(submitData)) {
window.neoConfirm('送信しますか? 送信後は変更・修正することはできません。', () => {

View File

@ -175,6 +175,7 @@ export default function ButtonForm(props: {
// ------------------------------------------------------------
// 제출 완료 된 매물의 경우 제출 권한 있으면 수정/삭제 불가능
if (mode === 'READ' && isSubmit && isSubmiter) {
return (
<>
@ -186,9 +187,7 @@ export default function ButtonForm(props: {
</>
)
}
//TODO: 추가확인 필요 (T01 계정이 어떤 조사매물을 수정/삭제 할 수 있는지)
if (mode === 'READ' && session?.role === 'T01' && (!isSubmit || props.data.basic.submissionTargetId !== session.storeId)) {
if (mode === 'READ' && session?.role === 'T01' && (!isSubmit || (props.data.basic.submissionTargetId && props.data.basic.submissionTargetNm))) {
return (
<>
<div className="sale-form-btn-wrap">

View File

@ -80,11 +80,10 @@ export default function DetailForm() {
const [roofInfoData, setRoofInfoData] = useState<SurveyDetailRequest>(roofInfoForm)
useEffect(() => {
if (Number(idParam) !== 0 && surveyDetail === null) {
if (Number(idParam) !== 0 || surveyDetail === null) {
alert('データが見つかりません。')
window.location.href = '/survey-sale'
}
if (surveyDetail && (mode === 'EDIT' || mode === 'READ')) {
const { id, uptDt, regDt, detailInfo, ...rest } = surveyDetail
setBasicInfoData(rest)

View File

@ -537,6 +537,7 @@ const SelectedBox = ({
</select>
<div className={`data-input ${column === 'constructionYear' ? 'flex' : ''}`}>
<input
id={`${column}Etc`}
type={column === 'constructionYear' ? 'number' : 'text'}
inputMode={column === 'constructionYear' ? 'numeric' : 'text'}
className="input-frame"
@ -642,6 +643,7 @@ const RadioSelected = ({
{(showEtcOption || column === 'insulationPresence') && (
<div className="data-input">
<input
id={`${column}Etc`}
type="text"
className="input-frame"
placeholder="-"

View File

@ -178,34 +178,44 @@ export function useSurvey(id?: number): {
})
const validateSurveyDetail = (surveyDetail: SurveyDetailRequest) => {
const etcFields = [
'installationSystem',
'constructionYear',
'rafterSize',
'rafterPitch',
'waterproofMaterial',
'structureOrder',
'insulationPresence',
] as const
// 상수 정의
const ETC_FIELDS = ['installationSystem', 'rafterSize', 'rafterPitch', 'waterproofMaterial', 'structureOrder'] as const
const emptyField = requiredFields.find((field) => {
if (etcFields.includes(field.field as (typeof etcFields)[number])) {
return (
surveyDetail[field.field as keyof SurveyDetailRequest] === null &&
(surveyDetail[`${field.field}Etc` as keyof SurveyDetailRequest] === null ||
surveyDetail[`${field.field}Etc` as keyof SurveyDetailRequest]?.toString().trim() === '')
)
} else {
return surveyDetail[field.field as keyof SurveyDetailRequest] === null
}
})
const SPECIAL_CONDITIONS = ['constructionYear', 'insulationPresence'] as const
const contractCapacity = surveyDetail.contractCapacity
if (contractCapacity && contractCapacity.trim() !== '' && contractCapacity.split(' ')?.length === 1) {
return 'contractCapacityUnit'
// 유틸리티 함수들
const isEmptyValue = (value: any): boolean => {
return value === null || value?.toString().trim() === ''
}
return emptyField?.field || ''
const checkRequiredField = (field: string): string => {
if (ETC_FIELDS.includes(field as (typeof ETC_FIELDS)[number])) {
if (
isEmptyValue(surveyDetail[field as keyof SurveyDetailRequest]) &&
isEmptyValue(surveyDetail[`${field}Etc` as keyof SurveyDetailRequest])
) {
return field
}
} else if (SPECIAL_CONDITIONS.includes(field as (typeof SPECIAL_CONDITIONS)[number])) {
if (surveyDetail[field as keyof SurveyDetailRequest] === '2' && isEmptyValue(surveyDetail[`${field}Etc` as keyof SurveyDetailRequest])) {
return `${field}Etc`
} else if (isEmptyValue(surveyDetail[field as keyof SurveyDetailRequest])) {
return field
}
}
return ''
}
// 필수 필드 체크
const emptyField = requiredFields.find((field) => checkRequiredField(field.field))
if (emptyField) return emptyField.field
// 계약 용량 단위 체크
const contractCapacity = surveyDetail.contractCapacity
if (contractCapacity?.trim() && contractCapacity.split(' ').length === 1) {
return 'contractCapacityUnit'
}
return ''
}
const getZipCode = async (zipCode: string): Promise<ZipCode[] | null> => {

View File

@ -21,18 +21,18 @@ export const SEARCH_OPTIONS = [
id: 'store',
label: '販売店名',
},
// {
// id: 'store_id',
// label: '販売店ID',
// },
{
id: 'store_id',
label: '販売店ID',
},
{
id: 'construction_point',
label: '施工店名',
},
// {
// id: 'construction_id',
// label: '施工店ID',
// },
{
id: 'construction_point_id',
label: '施工店ID',
},
]
export const SEARCH_OPTIONS_PARTNERS = [