물건상세 & 견적서 상세

This commit is contained in:
basssy 2024-11-26 18:29:34 +09:00
parent cd1a32eaf9
commit f4a4ac8e36
6 changed files with 95 additions and 69 deletions

View File

@ -20,6 +20,7 @@ import ProductFeaturesPop from './popup/ProductFeaturesPop'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
export default function Estimate({ params }) { export default function Estimate({ params }) {
const [handlePricingFlag, setHandlePricingFlag] = useState(false)
const [specialNoteFirstFlg, setSpecialNoteFirstFlg] = useState(false) const [specialNoteFirstFlg, setSpecialNoteFirstFlg] = useState(false)
const fixedKey = 'itemKey' const fixedKey = 'itemKey'
const [itemChangeYn, setItemChangeYn] = useState(false) const [itemChangeYn, setItemChangeYn] = useState(false)
@ -63,6 +64,7 @@ export default function Estimate({ params }) {
// List // List
const [specialNoteList, setSpecialNoteList] = useState([]) const [specialNoteList, setSpecialNoteList] = useState([])
const [popShowSpecialNoteList, setPopShowSpecialNoteList] = useState([])
const globalLocaleState = useRecoilValue(globalLocaleStore) const globalLocaleState = useRecoilValue(globalLocaleStore)
const { get, promisePost } = useAxios(globalLocaleState) const { get, promisePost } = useAxios(globalLocaleState)
@ -98,22 +100,40 @@ export default function Estimate({ params }) {
setDisplayItemList(res) setDisplayItemList(res)
} }
}) })
// API
// ()
//
let url = '/api/estimate/special-note-list'
get({ url: url }).then((res) => {
if (isNotEmptyArray(res)) {
setPopShowSpecialNoteList(res)
}
})
}, []) }, [])
useEffect(() => { useEffect(() => {
// API // API
// () // ()
//
if (!specialNoteFirstFlg) { if (!specialNoteFirstFlg) {
let url = `/api/estimate/special-note-list` let url = `/api/estimate/special-note-title-list`
get({ url: url }).then((res) => { get({ url: url }).then((res) => {
if (isNotEmptyArray(res)) { if (isNotEmptyArray(res)) {
// ATTR001ATTR002ATTR003ATTR007ATTR009ATTR010ATTR015ATTR019
if (estimateContextState?.estimateOption) { if (estimateContextState?.estimateOption) {
res.map((row) => { res.map((row) => {
let estimateOption = estimateContextState?.estimateOption?.split('、') let estimateOption = estimateContextState?.estimateOption?.split('、')
row.check = false row.check = false
estimateOption.map((row2) => { estimateOption.map((row2) => {
if (row2 === row.code) { if (row.pkgYn === '0') {
row.check = true if (row2 === row.code) {
row.check = true
}
} else {
if (row.code.includes(row2)) {
row.check = true
return
}
} }
}) })
//detail //detail
@ -135,48 +155,6 @@ export default function Estimate({ params }) {
} }
}, [estimateContextState?.estimateOption]) }, [estimateContextState?.estimateOption])
//
// useEffect(() => {
// // API
// // ()
// let url = `/api/estimate/special-note-title-list`
// // let url = `/api/estimate/special-note-list`
// get({ url: url }).then((res) => {
// if (isNotEmptyArray(res)) {
// if (estimateContextState?.estimateOption) {
// res.map((row) => {
// // console.log('API:::', row)
// //ATTR001ATTR002ATTR009ATTR010
// let estimateOption = estimateContextState?.estimateOption?.split('')
// row.check = false
// estimateOption.map((row2) => {
// if (row.pkgYn === '0') {
// if (row2 === row.code) {
// row.check = true
// }
// } else {
// if (row.code.includes(row2)) {
// row.check = true
// return
// }
// }
// })
// //detail
// //ATTR003,ATTR007
// if (row.code === 'ATTR003') {
// row.check = true
// }
// if (row.code === 'ATTR007') {
// row.check = true
// }
// })
// setSpecialNoteList(res)
// }
// }
// })
// }, [estimateContextState?.estimateOption])
//API //API
let begin = 1 let begin = 1
useEffect(() => { useEffect(() => {
@ -276,7 +254,9 @@ export default function Estimate({ params }) {
} }
//YJSS UNIT_PIRCE //YJSS UNIT_PIRCE
handlePricing('UNIT_PRICE') if (handlePricingFlag) {
handlePricing('UNIT_PRICE')
}
} else { } else {
if (specialNoteList.length > 0) { if (specialNoteList.length > 0) {
specialNoteList.map((item) => { specialNoteList.map((item) => {
@ -293,7 +273,9 @@ export default function Estimate({ params }) {
}) })
//YJOD UNIT_PRICE //YJOD UNIT_PRICE
handlePricing('UNIT_PRICE') if (handlePricingFlag) {
handlePricing('UNIT_PRICE')
}
} }
setItemChangeYn(true) setItemChangeYn(true)
@ -543,6 +525,7 @@ export default function Estimate({ params }) {
updates.itemGroup = res.itemGroup updates.itemGroup = res.itemGroup
updates.delFlg = '0' // 0 updates.delFlg = '0' // 0
updates.saleTotPrice = (res.salePrice * estimateContextState.itemList[index].amount).toString() updates.saleTotPrice = (res.salePrice * estimateContextState.itemList[index].amount).toString()
updates.amount = ''
if (estimateContextState.estimateType === 'YJSS') { if (estimateContextState.estimateType === 'YJSS') {
if (res.pkgMaterialFlg === '0') { if (res.pkgMaterialFlg === '0') {
@ -557,7 +540,8 @@ export default function Estimate({ params }) {
if (item.dispOrder === dispOrder) { if (item.dispOrder === dispOrder) {
return { ...item, ...updates } return { ...item, ...updates }
} else if (item.paDispOrder === dispOrder) { } else if (item.paDispOrder === dispOrder) {
return { ...item, delFlg: '0' } //
return { ...item, delFlg: '1' }
} else { } else {
return item return item
} }
@ -572,14 +556,14 @@ export default function Estimate({ params }) {
bomItem.salePrice = '0' bomItem.salePrice = '0'
bomItem.saleTotPrice = '0' bomItem.saleTotPrice = '0'
bomItem.unitPrice = '0' bomItem.unitPrice = '0'
bomItem.amount = bomItem.bomAmount // bomItem.amount = null
} else { } else {
bomItem.dispOrder = (index + 1 + Number(dispOrder)).toString() bomItem.dispOrder = (index + 1 + Number(dispOrder)).toString()
bomItem.paDispOrder = dispOrder bomItem.paDispOrder = dispOrder
bomItem.salePrice = '0' bomItem.salePrice = '0'
bomItem.saleTotPrice = '0' bomItem.saleTotPrice = '0'
bomItem.unitPrice = '0' bomItem.unitPrice = '0'
bomItem.amount = bomItem.bomAmount // bomItem.amount = null
} }
bomItem.delFlg = '0' bomItem.delFlg = '0'
@ -717,6 +701,11 @@ export default function Estimate({ params }) {
const volKw = (item.pnowW * amount) / 1000 const volKw = (item.pnowW * amount) / 1000
totVolKw += volKw totVolKw += volKw
} }
setEstimateContextState({
pkgTotPrice: estimateContextState.pkgAsp.replaceAll(',', '') * totVolKw,
})
//pkgTotPrice
// const saleTotPrice // const saleTotPrice
totAmount += amount totAmount += amount
if (item.pkgMaterialFlg === '1') { if (item.pkgMaterialFlg === '1') {
@ -735,7 +724,6 @@ export default function Estimate({ params }) {
} }
} }
}) })
supplyPrice = addSupplyPrice + Number(estimateContextState.pkgTotPrice) supplyPrice = addSupplyPrice + Number(estimateContextState.pkgTotPrice)
vatPrice = supplyPrice * 0.1 vatPrice = supplyPrice * 0.1
totPrice = supplyPrice + vatPrice totPrice = supplyPrice + vatPrice
@ -905,6 +893,7 @@ export default function Estimate({ params }) {
checked={estimateContextState?.estimateType === 'YJSS' ? true : false} checked={estimateContextState?.estimateType === 'YJSS' ? true : false}
onChange={(e) => { onChange={(e) => {
// //
setHandlePricingFlag(true)
setEstimateContextState({ estimateType: e.target.value }) setEstimateContextState({ estimateType: e.target.value })
}} }}
/> />
@ -918,6 +907,7 @@ export default function Estimate({ params }) {
value={'YJOD'} value={'YJOD'}
checked={estimateContextState?.estimateType === 'YJOD' ? true : false} checked={estimateContextState?.estimateType === 'YJOD' ? true : false}
onChange={(e) => { onChange={(e) => {
setHandlePricingFlag(true)
setEstimateContextState({ estimateType: e.target.value }) setEstimateContextState({ estimateType: e.target.value })
}} }}
/> />
@ -1101,7 +1091,9 @@ export default function Estimate({ params }) {
settingShowContent(row.code, event) settingShowContent(row.code, event)
}} }}
/> />
<label htmlFor={row.code}>{row.codeNm}</label> <label htmlFor={row.code}>
{row.codeNm} / {row.code}
</label>
</div> </div>
</div> </div>
) )
@ -1188,7 +1180,7 @@ export default function Estimate({ params }) {
</div> </div>
</td> </td>
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgWeight')}</th> <th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgWeight')}</th>
<td>{convertNumberToPriceDecimalToFixed(estimateContextState?.totVolKw, 2)}</td> <td>{convertNumberToPriceDecimalToFixed(estimateContextState?.totVolKw, 3)}</td>
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgPrice')}</th> <th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgPrice')}</th>
<td>{convertNumberToPriceDecimal(estimateContextState?.pkgTotPrice)}</td> <td>{convertNumberToPriceDecimal(estimateContextState?.pkgTotPrice)}</td>
</tr> </tr>
@ -1222,6 +1214,7 @@ export default function Estimate({ params }) {
type="button" type="button"
className="btn-origin grey ml5" className="btn-origin grey ml5"
onClick={() => { onClick={() => {
setHandlePricingFlag(true)
handlePricing(showPriceCd) handlePricing(showPriceCd)
}} }}
> >
@ -1429,7 +1422,7 @@ export default function Estimate({ params }) {
</div> </div>
{productFeaturesPopupOpen && ( {productFeaturesPopupOpen && (
<ProductFeaturesPop <ProductFeaturesPop
specialNoteList={specialNoteList} popShowSpecialNoteList={popShowSpecialNoteList}
showProductFeatureData={showProductFeatureData} showProductFeatureData={showProductFeatureData}
setProductFeaturesPopupOpen={setProductFeaturesPopupOpen} setProductFeaturesPopupOpen={setProductFeaturesPopupOpen}
/> />

View File

@ -1,13 +1,13 @@
'use client' 'use client'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
export default function ProductFeaturesPop({ specialNoteList, showProductFeatureData, setProductFeaturesPopupOpen }) { export default function ProductFeaturesPop({ popShowSpecialNoteList, showProductFeatureData, setProductFeaturesPopupOpen }) {
const [showSpecialNoteList, setShowSpecialNoteList] = useState([]) const [showSpecialNoteList, setShowSpecialNoteList] = useState([])
const { getMessage } = useMessage() const { getMessage } = useMessage()
useEffect(() => { useEffect(() => {
let pushData = [] let pushData = []
specialNoteList.map((row) => { popShowSpecialNoteList.map((row) => {
let option = showProductFeatureData.split('、') let option = showProductFeatureData.split('、')
option.map((row2) => { option.map((row2) => {
if (row.code === row2) { if (row.code === row2) {
@ -16,7 +16,7 @@ export default function ProductFeaturesPop({ specialNoteList, showProductFeature
}) })
}) })
setShowSpecialNoteList(pushData) setShowSpecialNoteList(pushData)
}, [specialNoteList]) }, [popShowSpecialNoteList])
return ( return (
<div className="modal-popup"> <div className="modal-popup">

View File

@ -142,6 +142,16 @@ export default function StuffDetail() {
headerName: getMessage('stuff.detail.planGridHeader.capacity'), headerName: getMessage('stuff.detail.planGridHeader.capacity'),
width: 120, width: 120,
cellStyle: { justifyContent: 'flex-end' /* 우측정렬*/ }, cellStyle: { justifyContent: 'flex-end' /* 우측정렬*/ },
cellRenderer: (params) => {
let origin = params.value
let capacity
if (origin) {
capacity = origin / 1000
return capacity.toFixed(3)
} else {
return null
}
},
}, },
{ {
field: 'roofMaterialIdMulti', field: 'roofMaterialIdMulti',
@ -170,8 +180,8 @@ export default function StuffDetail() {
}, },
}, },
{ {
field: 'constructSpecification', field: 'constructSpecificationMulti',
headerName: getMessage('stuff.detail.planGridHeader.constructSpecification'), headerName: getMessage('stuff.detail.planGridHeader.constructSpecificationMulti'),
wrapText: true, wrapText: true,
autoHeight: true, autoHeight: true,
cellStyle: { justifyContent: 'flex-start' /* 좌측정렬*/ }, cellStyle: { justifyContent: 'flex-start' /* 좌측정렬*/ },

View File

@ -141,7 +141,6 @@ export const useEstimateController = (planNo) => {
return alert(getMessage('estimate.detail.save.requiredEstimateDate')) return alert(getMessage('estimate.detail.save.requiredEstimateDate'))
} }
// console.log('첨부파일:::::', estimateData.fileList)
//첨부파일을 첨부안했는데 //첨부파일을 첨부안했는데
//아이템 fileUploadFlg가1(첨부파일 필수)이 1개라도 있는데 후일 자료 제출(fileFlg) 체크안했으면(0) alert 저장안돼 //아이템 fileUploadFlg가1(첨부파일 필수)이 1개라도 있는데 후일 자료 제출(fileFlg) 체크안했으면(0) alert 저장안돼
let fileFlg = true let fileFlg = true
@ -159,8 +158,34 @@ export const useEstimateController = (planNo) => {
}) })
} }
} }
let itemFlg = true
estimateData.itemList.map((item) => {
item.amount = item.amount?.replaceAll(',', '')
item.salePrice = parseFloat(item.salePrice?.replaceAll(',', '')).toFixed(2)
item.saleTotPrice = parseFloat(item.saleTotPrice?.replaceAll(',', '')).toFixed(2)
if (flag && fileFlg) { if (!item.paDispOrder) {
if (itemFlg) {
if (isNaN(item.amount)) {
item.amount = 0
} else {
Number(item.amount)
}
if (item.amount < 1) {
itemFlg = false
return alert(getMessage('estimate.detail.save.requiredAmount'))
}
if (Number(item.salePrice) < 1) {
itemFlg = false
return alert(getMessage('estimate.detail.save.requiredSalePrice'))
}
}
}
})
if (flag && fileFlg && itemFlg) {
//1. 첨부파일 저장시작 //1. 첨부파일 저장시작
const formData = new FormData() const formData = new FormData()
formData.append('file', estimateData.fileList) formData.append('file', estimateData.fileList)
@ -186,12 +211,6 @@ export const useEstimateController = (planNo) => {
} }
console.log('최종 아이템 정보::;', estimateData.itemList) console.log('최종 아이템 정보::;', estimateData.itemList)
estimateData.itemList.map((item) => {
item.amount = item.amount?.replaceAll(',', '')
item.salePrice = parseFloat(item.salePrice?.replaceAll(',', '')).toFixed(2)
item.saleTotPrice = parseFloat(item.saleTotPrice?.replaceAll(',', '')).toFixed(2)
})
console.log('최종 정보::;', estimateData) console.log('최종 정보::;', estimateData)
//2. 상세데이터 저장 //2. 상세데이터 저장
// return // return

View File

@ -729,7 +729,7 @@
"stuff.detail.planGridHeader.moduleModel": "モジュール", "stuff.detail.planGridHeader.moduleModel": "モジュール",
"stuff.detail.planGridHeader.capacity": "システム容量", "stuff.detail.planGridHeader.capacity": "システム容量",
"stuff.detail.planGridHeader.roofMaterialIdMulti": "屋根材", "stuff.detail.planGridHeader.roofMaterialIdMulti": "屋根材",
"stuff.detail.planGridHeader.constructSpecification": "施工方法", "stuff.detail.planGridHeader.constructSpecificationMulti": "施工方法",
"stuff.detail.planGridHeader.supportMethodIdMulti": "架台", "stuff.detail.planGridHeader.supportMethodIdMulti": "架台",
"stuff.detail.planGridHeader.pcTypeNo": "パワーコンディショナー", "stuff.detail.planGridHeader.pcTypeNo": "パワーコンディショナー",
"stuff.detail.planGridHeader.management": "管理", "stuff.detail.planGridHeader.management": "管理",
@ -895,6 +895,8 @@
"estimate.detail.save.requiredCharger": "担当者は必須です.", "estimate.detail.save.requiredCharger": "担当者は必須です.",
"estimate.detail.save.requiredObjectName": "案件名は必須です.", "estimate.detail.save.requiredObjectName": "案件名は必須です.",
"estimate.detail.save.requiredEstimateDate": "見積日は必須です.", "estimate.detail.save.requiredEstimateDate": "見積日は必須です.",
"estimate.detail.save.requiredAmount": "数量は0より大きい値を入力してください.",
"estimate.detail.save.requiredSalePrice": "単価は0より大きい値を入力してください.",
"estimate.detail.reset.confirmMsg": "保存した見積書情報が初期化され、図面情報が反映されます。本当に初期化しますか?", "estimate.detail.reset.confirmMsg": "保存した見積書情報が初期化され、図面情報が反映されます。本当に初期化しますか?",
"simulator.title.sub1": "物件番号", "simulator.title.sub1": "物件番号",
"simulator.title.sub2": "作成日", "simulator.title.sub2": "作成日",

View File

@ -739,7 +739,7 @@
"stuff.detail.planGridHeader.moduleModel": "모듈", "stuff.detail.planGridHeader.moduleModel": "모듈",
"stuff.detail.planGridHeader.capacity": "시스템용량", "stuff.detail.planGridHeader.capacity": "시스템용량",
"stuff.detail.planGridHeader.roofMaterialIdMulti": "지붕재", "stuff.detail.planGridHeader.roofMaterialIdMulti": "지붕재",
"stuff.detail.planGridHeader.constructSpecification": "시공방법", "stuff.detail.planGridHeader.constructSpecificationMulti": "시공방법",
"stuff.detail.planGridHeader.supportMethodIdMulti": "가대", "stuff.detail.planGridHeader.supportMethodIdMulti": "가대",
"stuff.detail.planGridHeader.pcTypeNo": "파워컨디셔너", "stuff.detail.planGridHeader.pcTypeNo": "파워컨디셔너",
"stuff.detail.planGridHeader.management": "관리", "stuff.detail.planGridHeader.management": "관리",
@ -905,6 +905,8 @@
"estimate.detail.save.requiredCharger": "담당자는 필수값 입니다.", "estimate.detail.save.requiredCharger": "담당자는 필수값 입니다.",
"estimate.detail.save.requiredObjectName": "안건명은 필수값 입니다.", "estimate.detail.save.requiredObjectName": "안건명은 필수값 입니다.",
"estimate.detail.save.requiredEstimateDate": "견적일은 필수값 입니다.", "estimate.detail.save.requiredEstimateDate": "견적일은 필수값 입니다.",
"estimate.detail.save.requiredAmount": "수량은 0보다 큰값을 입력해주세요.",
"estimate.detail.save.requiredSalePrice": "단가는 0보다 큰값을 입력해주세요.",
"estimate.detail.reset.confirmMsg": "저장된 견적서 정보가 초기화되고, 도면정보가 반영됩니다. 정말로 초기화 하시겠습니까?", "estimate.detail.reset.confirmMsg": "저장된 견적서 정보가 초기화되고, 도면정보가 반영됩니다. 정말로 초기화 하시겠습니까?",
"simulator.title.sub1": "물건번호", "simulator.title.sub1": "물건번호",
"simulator.title.sub2": "작성일", "simulator.title.sub2": "작성일",