From d16645d0aa7b56319ab25832d52377f40bfede92 Mon Sep 17 00:00:00 2001 From: jyha00 Date: Tue, 1 Jul 2025 16:34:43 +0900 Subject: [PATCH] =?UTF-8?q?=ED=95=98=EC=88=98=EC=9E=AC=EC=9D=B4=EC=9A=A9?= =?UTF-8?q?=EC=8B=A4=EC=A0=81=20=EB=93=B1=EB=A1=9D=20=ED=8C=9D=EC=97=85=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EC=88=98=EC=A0=95,=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95,=20=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EB=B8=94=20merge=20=EC=B6=94=EA=B0=80,=20=EC=86=8C?= =?UTF-8?q?=EA=B3=84=20=EB=B0=8F=20=EC=B4=9D=ED=95=A9=EA=B3=84=20=EB=B0=B0?= =?UTF-8?q?=EA=B2=BD=EC=83=89=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../prfmncReg/pbnstPrfmncReg/page.tsx | 38 +++-- .../prfmncReg/pbnstPrfmncReg/headList.tsx | 27 ++-- apps/wr/components/lib/func/TableData.tsx | 151 ++++++++++++------ .../pbnPrfExcelModal/pbnPrfExcelModal.tsx | 123 +++++++------- apps/wr/public/sample_pbnstPrfmncReg.xlsx | Bin 13777 -> 13806 bytes 5 files changed, 208 insertions(+), 131 deletions(-) diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx index 6be50a8c5..10dd7ccb6 100644 --- a/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx @@ -25,7 +25,7 @@ import { } from "@common/components/ui"; import { useState, useEffect, useCallback } from "react"; import { set } from "react-hook-form"; -import { Toaster } from "react-hot-toast"; +import toast, { Toaster } from "react-hot-toast"; import { headMakeprfmnc } from "../chkgdnReg/TableHead"; import { InputTableBody } from "@/components/lib/func/TableData"; import { @@ -51,8 +51,8 @@ export default function prfmncPrfmncReg() { }>({ isModal: false, data: {} as FcPrfType }); const [inputData, setInputData] = useState(); const [pbnstRuseFcltPk, setPbnstRuseFcltPk] = useState(); - const [pageNation , setPageNation] = useState(1); - + const [pageNation, setPageNation] = useState(1); + const [cellNum, setCellNum] = useState(); const [searchYear, setSearchYear] = useState( String(new Date().getFullYear()) ); @@ -76,7 +76,7 @@ export default function prfmncPrfmncReg() { ); prfmncHasuInit(String(pageNation), "41"); } - }, [inputData, searchYear, pbnstRuseFcltPk,prfmncHasuInit,pageNation]); + }, [inputData, searchYear, pbnstRuseFcltPk, prfmncHasuInit, pageNation]); @@ -88,10 +88,16 @@ export default function prfmncPrfmncReg() { isModal: false, data: prfmncRes[index] || ({} as FcPrfType), }); - const inUsageData = structuredClone(initValInUsage); - const outUsageData = structuredClone(initValOutUsage); - const inSubtotal = structuredClone(subTotalObj); - const outSubtotal = structuredClone(subTotalObj); + const inUsageData = structuredClone(initValInUsage).map(row => ({ + ...row, + 구분: "장내용수", + })); + const outUsageData = structuredClone(initValOutUsage).map(row => ({ + ...row, + 구분: "장외용수", + })); + const inSubtotal = { ...structuredClone(subTotalObj), 구분: "장내용수" }; + const outSubtotal = { ...structuredClone(subTotalObj), 구분: "장외용수" }; if (prfmncRes[index]?.prfList) { prfmncRes[index].prfList?.forEach((prfItem) => { const month = Number(prfItem?.ym?.slice(4)); // "MM" @@ -127,7 +133,7 @@ export default function prfmncPrfmncReg() { }); inUsageData.push(inSubtotal); outUsageData.push(outSubtotal); - const usageTotalObj: { [key: string]: any } = structuredClone(totalObj); + const usageTotalObj: { [key: string]: any } = { ...structuredClone(totalObj), 구분: "총합계", 용수명: "" }; for (const key in usageTotalObj) { if (["usage", "gubun", "edit"].includes(key)) continue; const val = @@ -162,7 +168,7 @@ export default function prfmncPrfmncReg() {
- + <Title title={"하수재이용 실적 등록"} /> <SearchDiv> <SearchFormLeft> <div className="col-span-2 flex flex-row space-x-2"> @@ -197,7 +203,7 @@ export default function prfmncPrfmncReg() { <SearchFormRight className="w-2/12 mx-5 flex flex-col items-center justify-center space-x-2 "> <div className="space-y"> <div className="flex flex-row space-x-2"> - <Button size={"sm"} onClick={(e) => {}}> + <Button size={"sm"} onClick={(e) => { }}> 조회 </Button> <Button @@ -211,7 +217,12 @@ export default function prfmncPrfmncReg() { <Button size={"sm"} onClick={() => { - setIsExcelOPen({ ...isExcelOpen, isModal: true }); + if (cellNum === undefined) { + toast.error("하수처리재이용시설을 선택해주세요.") + return; + } else { + setIsExcelOPen({ ...isExcelOpen, isModal: true }); + } }} > 파일등록 @@ -238,6 +249,7 @@ export default function prfmncPrfmncReg() { headName={"하수재이용시설 목록"} cellClick={(index: number | undefined, headId: string) => { cellClick(index, headId); + setCellNum(index ?? 0); }} onPageChange={setPageNation} children={undefined} @@ -266,7 +278,7 @@ export default function prfmncPrfmncReg() { </div> </ContentsDiv> <UiModal - bodyClass={""} + bodyClass={"w-[30vw] max-w-none"} body={<PbnPrfExcelModal data={isExcelOpen.data}></PbnPrfExcelModal>} open={isExcelOpen.isModal} onOpenChange={() => { diff --git a/apps/wr/app/store/prfmncReg/pbnstPrfmncReg/headList.tsx b/apps/wr/app/store/prfmncReg/pbnstPrfmncReg/headList.tsx index 544f07516..abde1778f 100644 --- a/apps/wr/app/store/prfmncReg/pbnstPrfmncReg/headList.tsx +++ b/apps/wr/app/store/prfmncReg/pbnstPrfmncReg/headList.tsx @@ -4,7 +4,7 @@ import type { TableUpperProps } from "../../common/type/header"; export const pbnPrfRegExcelZod = z.object({ ym: z.string().default(""), bscFctNm: z.string().default(""), - pbnstRuseFcltFk:z.string(), + pbnstRuseFcltFk: z.string(), pbnstRuseFcltNm: z.string().default(""), file: z.instanceof(File).optional(), }); @@ -18,20 +18,21 @@ export const pbnstPrfmncHeadListExport: TableUpperProps[] = [ ]; export const monthHeadListExport: TableUpperProps[] = [ + { id: "구분", title: "구분", mergeCell: true }, { id: "용수명", title: "용수명" }, { id: "total", title: "계" }, - { id: "1월", title: "1월" ,edit: true }, - { id: "2월", title: "2월" ,edit: true }, - { id: "3월", title: "3월" ,edit: true }, - { id: "4월", title: "4월" ,edit: true }, - { id: "5월", title: "5월" ,edit: true }, - { id: "6월", title: "6월" ,edit: true }, - { id: "7월", title: "7월" ,edit: true }, - { id: "8월", title: "8월" ,edit: true }, - { id: "9월", title: "9월" ,edit: true }, - { id: "10월", title: "10월" ,edit: true }, - { id: "11월", title: "11월" ,edit: true }, - { id: "12월", title: "12월" ,edit: true }, + { id: "1월", title: "1월", edit: true }, + { id: "2월", title: "2월", edit: true }, + { id: "3월", title: "3월", edit: true }, + { id: "4월", title: "4월", edit: true }, + { id: "5월", title: "5월", edit: true }, + { id: "6월", title: "6월", edit: true }, + { id: "7월", title: "7월", edit: true }, + { id: "8월", title: "8월", edit: true }, + { id: "9월", title: "9월", edit: true }, + { id: "10월", title: "10월", edit: true }, + { id: "11월", title: "11월", edit: true }, + { id: "12월", title: "12월", edit: true }, ]; diff --git a/apps/wr/components/lib/func/TableData.tsx b/apps/wr/components/lib/func/TableData.tsx index dbb3aa7a6..39c8b7739 100644 --- a/apps/wr/components/lib/func/TableData.tsx +++ b/apps/wr/components/lib/func/TableData.tsx @@ -174,8 +174,6 @@ export const chRowspanTable = ( ); }; - - export const headVisibleChange = (headList: TableUpperProps[], isEdit: boolean) => { return headList.forEach((head) => { if (head.edit !== undefined) @@ -187,63 +185,124 @@ export const headVisibleChange = (headList: TableUpperProps[], isEdit: boolean) }); } - const handleChange = ( rowIndex: number, field: any, value: string | number, - setInputData: (data:any) => void + setInputData: (data: any) => void ) => { - if(Number(value) < 0 ||! Number(value)){ - value = 0; - }else{ + if (Number(value) < 0 || !Number(value)) { + value = 0; + } else { value = Number(value); } - setInputData((prevData:any) => - prevData?.map((row:any, index: number) => { - if (index === rowIndex) { - return { - ...row, - [field ]: value, - }; - } - return row; - }) - ); + setInputData((prevData: any) => + prevData?.map((row: any, index: number) => { + if (index === rowIndex) { + return { + ...row, + [field]: value, + }; + } + return row; + }) + ); }; ; +export const InputTableBody = ( + chgRes: any[] | [], + headList: TableUpperProps[], + setInputData: (data: any[]) => void +) => { + // mergeCell 처리용 + const getRowSpan = (data: any[], key: string, rowIndex: number) => { + if (rowIndex > 0 && data[rowIndex][key] === data[rowIndex - 1][key]) { + return 0; // 이전과 같으면 셀을 그리지 않음 + } + let span = 1; + for (let i = rowIndex + 1; i < data.length; i++) { + if (data[i][key] === data[rowIndex][key]) span++; + else break; + } + return span; + }; - -export const InputTableBody = (chgRes: any[] | [] ,headList:TableUpperProps[], setInputData: (data: any[]) => void) => { - return ( + return ( <> - {chgRes.map((data, dataIndex) => ( - <TableRow key={dataIndex + "row"}> - {headList.map((head, headIndex) => ( - <TableCell key={head.id + headIndex} className="w-36" > - {head.edit ===true && data.edit !==false? - <Input - className={`${head.id !== "utztnUsgCd" ? "text-right" : "text-center"} !text-xl h-10 w-full`} - onChange={(e) => - handleChange(dataIndex, head.id, e.target.value,setInputData) - } - value={data[head.id as keyof any] ?? ""} - /> : ( - <div - className={` - ${head.id !== "utztnUsgCd" ? "text-right" : "text-center"} - !text-xl w-full h-10 - `} + {chgRes.map((data, dataIndex) => { + // 소계/총합계 행 판별 + const isSubTotal = data["용수명"] === "소계"; + const isTotal = data["구분"] === 0; + + const bgClass = isTotal + ? "bg-[#d5e1eb] font-bold" + : isSubTotal + ? "bg-[#e6eef5] font-semibold" + : ""; + + return ( + <TableRow key={dataIndex + "row"}> + {headList.map((head, headIndex) => { + // 총합계 행이면 "구분"에서 colSpan=2로 병합 + if ( + data["구분"] === 0 && + head.id === "구분" + ) { + return ( + <TableCell + key={head.id + headIndex} + colSpan={2} + className="font-bold text-center bg-[#d5e1eb]" > - {data[head.id as keyof any] ?? ""} - </div> - ) + 총합계 + </TableCell> + ); + } + // 총합계(합계) 행이면 "용수명" 컬럼은 렌더링하지 않음 + if ( + data["구분"] === 0 && + head.id === "용수명" + ) { + return null; + } + // mergeCell 처리 + if (head.mergeCell) { + const rowSpan = getRowSpan(chgRes, head.id, dataIndex); + if (rowSpan === 0) return null; + return ( + <TableCell key={head.id + headIndex} rowSpan={rowSpan} className={`w-36 align-middle text-center whitespace-nowrap ${bgClass}`}> + {data[head.id as keyof any] ?? ""} + </TableCell> + ); } - </TableCell> - ))} - </TableRow> - ))} + // 기본 셀 + return head.edit === true && data.edit !== false ? ( + <TableCell key={head.id + headIndex} className={`w-36 ${bgClass}`}> + <Input + className={`${head.id !== "utztnUsgCd" ? "text-right" : "text-center"} !text-xl h-10 w-full`} + onChange={(e) => + handleChange(dataIndex, head.id, e.target.value, setInputData) + } + value={data[head.id as keyof any] ?? ""} + /> + </TableCell> + ) : ( + <TableCell key={head.id + headIndex} className={`w-36 ${bgClass}`}> + <div + className={` + ${head.id !== "utztnUsgCd" ? "text-right" : "text-center"} + !text-xl w-full h-10 + `} + > + {data[head.id as keyof any] ?? ""} + </div> + </TableCell> + ); + })} + </TableRow> + ); + })} </> ); -} \ No newline at end of file +}; \ No newline at end of file diff --git a/apps/wr/components/ui/modal/chkgd/pbnPrfExcelModal/pbnPrfExcelModal.tsx b/apps/wr/components/ui/modal/chkgd/pbnPrfExcelModal/pbnPrfExcelModal.tsx index 28dc882c3..fb6ba9b22 100644 --- a/apps/wr/components/ui/modal/chkgd/pbnPrfExcelModal/pbnPrfExcelModal.tsx +++ b/apps/wr/components/ui/modal/chkgd/pbnPrfExcelModal/pbnPrfExcelModal.tsx @@ -52,6 +52,7 @@ export default function PbnPrfExcelModal({ data }: { data: FcPrfType }) { useEffect(() => { if (files) { + console.log("이런") const file = files[0]; if (form.getValues("ym").length < 1) { ToastFormUi({ @@ -62,11 +63,12 @@ export default function PbnPrfExcelModal({ data }: { data: FcPrfType }) { return; } - if (file) + if (file) { filePicked(file, 0).then((res) => { if (res !== undefined) - setExcelData(excelToPbnPrfData(res as unknown as JSON[], form.getValues("ym"),form.getValues('pbnstRuseFcltFk') ) as PrfType[]) + setExcelData(excelToPbnPrfData(res as unknown as JSON[], form.getValues("ym"), form.getValues('pbnstRuseFcltFk')) as PrfType[]) }); + } } }, [files]); @@ -75,82 +77,85 @@ export default function PbnPrfExcelModal({ data }: { data: FcPrfType }) { <div> <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)}> - <div> + <div className="flex justify-between items-center"> <Title title={"하수재이용 실적등록"}> -
-
-

- {"점검정보 입력"} -

- -
+

+ {"점검정보 입력"} +

-
+
( field.onChange(val)} /> )} /> - - ( - - - - )} - /> - ( - - - - )} - /> - - ( - - { - if (files) setFiles(files); - }} - fileTypes="xlsx" - maxFiles={1} - > - - )} - /> +
+
+ ( + + + + )} + /> +
+
+ ( + + + + )} + /> +
+
+
+ ( + + { + if (files) setFiles(files); + }} + fileTypes="xlsx" + maxFiles={1} + > + + )} + /> +
diff --git a/apps/wr/public/sample_pbnstPrfmncReg.xlsx b/apps/wr/public/sample_pbnstPrfmncReg.xlsx index 67f0d559e096443366eeff0f951b5648e422a972..1f2ff81aa24e1dce6ca8e8bce7fd7d9f54ed91ad 100644 GIT binary patch delta 5703 zcmZ8lWmFVUw;ejAyBRR0lvY|mTDofhhZboVQW~T|QbKa*l#Y?^4oT_f_ug7> z`QH6??^^qub$*<4?%sRS;l!av7z>L6jPM9T1_0JzQdm?_5~WD>eQTvfm64f=i$QTS#AMS_lT|vu?>V+=u_$x9fsEmQ}y= zw(*M&N=I&w6Nv&<0d|Wm7vI7BkioFehB0w?rwx$7N%Uw`5B3i+8fA*cJ&R4~IAuF; z*mv;&n6!n^(R84@i8}um%XUT_j`yr790TaZ_B#i%+F5%sIxr8Bv$nWQ%a>ZA1Z7h2 z1iN9(<&>|ZWuO<41vJ!o)dG5Zq(&M~s5}Gqrexf}3uK1k7y%D^nM4@ugUidW-EZ*B zc^|K_DI-MkJQR~>_=Tte+rrE)y@&qaPDL2;G1xbum(7XGa0NH|-78KSF&YN}jr4q# z7;#Vv&fQ1|M|5_Q+rm{3=qv&JVBXi^PV{9XDN_z)j)so`&fmSiQo*#(q%KDl_GAu6 zdeK?&Tn#Zi(tZi2-3@xhl~IsD^4+lqsUcn7xBRAdC`;!zMQp)PV#JvfSS4jUNlh9{ z(y$b&qOBpu1QQzituFN}>#26IXM)+8zYqgWvk)yMzDu7Be`2?n^h#w_V|FKGVvC>t z{=1tex2D&M4;!+~b0p&6!=7o4-f(m0GLc;X&OHD-WjQ3i@dzUPjBz^QT>0#muSuQ|gSQJ*2a>fFC|B=3zbEaoLrqjF@ zf?nTfC`^~)Qsp6kCGI1kD!SdB^d9QOaJUHS(TW?38j)Htd4!lhUhTT1Nj-g~vu0!U zbfQDI2O2VHhg`&Tz0cceIOM<*Ly{|3(U)oaocG*(@IZYRhbnWaXEZ^QlIBt)w9&kEGEV+l27 z#W|#0oN*^cVh#&2f_fL0Opp^crB1hB8iPcWZQ!K*dZUd>_X(%Pp}xv;1eO zWP(d^KU0(dmJV75?~Lxb>^^i&M^=_TUMFNHi?O`Uu)VOIc*XUMKiaV+C`~)tph5sd zTiV%QocvbYdny0-2T`yyU`^51@+i(Fz-;` zK+3x>GAqkq49fZ$eW`v~BWVc|dG@-xs)0C$g+GL}ozXW53#@*+kLE!S;Ic{bvpQI~ zwd|gHlv|$~Ulq1jHMgeOIHWA2bU$V|Z5fxc?cJ3Y+u099T!rAAlO4@$v@a7azW3~! zO9{^Z=8RiuKOa>boIk7|o<{}Gu@RgsYomnHSRKYn_feWsdL2-syfW)}%Ntz|@=kGR zB0P8{BD?Ovgt}Y#%AEkZ52kOykgzIGYCcrE%E`oe8__OVbpi``%VNDMbtTQa@i{vb z4wGx+Zm*ylhN+!?GL|Krdb$9j+CAG5h2Y;TzQz`f&J|`d;g$_t;CNF_T9#=srBl^1 z_;kO_tKVtXU@(>%rrNFMRcgwSNy{K$BE(Ydtf4%+Fw=LYh?5TG>7z8#@oV&>K#V<- zi?WQ+gftmlk&5l=L`NR&Jf++@Uwb`cl$YwW1nhLr8etP5R&&(wFs5Omu6HY6Pd&k+ zp6KgV2Vu*bL!MOlZC&7}Z?oo)kx%6(=yF9nKA%{^c`8c>_0}{qTLzt9;08R#;?*oJ zV91Pvu>;3HgLA;Ap8ln$m;TukpXH>|uYbT`AUxxR9!cSQUY~ z{-u&Q8X@bn%uBzBou}>TpHb=!3F2|EP=eO=^)LVcG1zbF*U%B*QO654KO_s~8trOF8^l?VrEp&b0*+ZspX)n5H(%03 zs{SR+6}4`*FUa*)L9B%lc~JgyJ*;DmYzfJv7b*^QVNg-Z>|BLJsp6rCQT86{E(igb zDy5|0kH(ms){%^ouB9SabxPcyg$EJz!!{UlWi~D1BsZ|rVOu-4+U)?mwM7^v>7Lh> zJ#(xeCrMU2?EP4ML|xK~iWs@^*C`^P-fKJ5YOWpDYB7`D`W4Kt>Y8U;iXzJb!jE(4IT)FX0*blDOup_+ zAM7JgVC8-SzK!VKr(77JbC@}8X&>jsLtY>4P916KXfV#)lg75~%UjZ?Vmp@(zLDPOL*cP1~TqAJnZ(FDPgG)VbEiOEZ zV@EDBBEG28G8P`6AXa=e7G-r7Z3PB)4ArUiV`6t31C^aCe4beRyccE3q`3rPgX`uc zvC-3G>n-Zk7@Ut`uD+0o{%zv!^?ey?jCv1`x&K_!@M8u>2sgZ*P}W^H>@1(-?&6_* ztWS!-C${jH_je+kBY`@sFm1y&ulHpb*A*tRB6xEX;@=@%buwP3rTixAF?a#E90t>- ztk;79;no~Zx*d%i(wC-vEs0+5icuIPN(ZTK)Z{!v0whYQa;@ld$|uu=0(3X)D+x=f z8d)mBl-?4sP7;zTT@%r3%P{58Y0E(6a%i<>EOY+8LrrP4Tb4V&Vfoc-(qXP|56PwM zzm!wUK^mqjMwxcXrTmnWN#dE&&%L!`fBwhmda+&d-9l&lD5-k?NBnKVX*$7-s6oiY zphWEG{2+2H*UTU=mTPXXmCJG;V zF-5xh`?%n6fbwO}Lvz;0a<1udg2azFi97tH;n04u8KP?9k$!mrYT@~s9*pdXX{^9( z&;*uTHfRdVGTXJB_@`%g3sj?7lrb3@|FE9K*XR;!%uNN4wT`~>3Q1|^a+U`1qodiSDqpgP1*uS@rJRnG<%dxj=6Dy>XbjlVZnk7+4$c& zYXQoRaOW#IM{RHhcZBq-Q>jz3Unk9K+f0gU`W)CoRv1X!P1jJ%q$}= z*|GH3d#dg@H_$s=jbpO(x-Odkm)c`&eNE}Sk}sLKDxA4Ic{qknF)kKLOwC&%;<@hF zfPfgHFMdR6tbvs5Io^}}c}w685EsT1?Db;I(W3bpTv^Po|wl%$p+0}F=d11uu8<&)mXC*!=j00#jf>9 zt1dA~18a=?A60$6=Yy1jFiyoa>{*k!QyNgqT{`-Zl|$t1tw+q z#;l*DeX%z>Z#y z^<^LWLBHa1ZcjerTMERetU3kV$gVU+(a5ecMdSNahMxGmDtXCQcVIvRrqi|I2b2L- z5kA&4M%=|5T13|*EYo{BpG!iO@z-_WLZaV41xI6A#+g9tUq@vnkB=$%&8kF`Lo%Ft z3{U8ss*jG>m${d<%mYAemio}!9r(CagK-Zp+W}WN=cR6K)&7-)B<$lVd>p4S+}Lq3 z*IX;Ubt_{u>0E44FZ+d|P};s0QR-0#t+NumW?_=k8`66BcE;81=d*E7JQrpFV($uk z`F7?ZckYy_%*;F6q>gFZ@|sxu6EKfWpt;WFqXM6>@R>(E2b!3t=qPASXv7uKJF)b< zXL&C5mwx}{?>ShB3b2+ zo&G;hnZ<6hh!K7;;mKfUaD)O0jS-A*N@X;Pnz?LEpSLi+iO;=MapQ{}p$S}U84f<^ zfnpF2eYc5dCXPDXauPkcpDX-ePCr_wLCOhQrQ<*&(twU6)9@4 zA&9ZiOVvWFc6p!7(tlXl0mhh#v@9ho*HApUWTQ_krAm~ria3Y+n3ii$3$2`-53@*} zUYsKy6=0d1-o|J7J^l&DLt!=}Yb)Rz=vp0b@Pe^tUIz9`_ZdOG+K8gJyBU14lnW2P zv5+jk-g?|gPC$|?zvzX42ucqf16JDGZ8Lk1{M*AwK(`D=4V@=I6B!rqq-NfW5zAuO z8yClVvQA`?8afiGile1>WqsV>)rV8HJv7WK<)=s=a0?+{Xm!ZbPd9Cb!K+E3OU*66 zzNO{n$w#vW)pWvCaDWu( zKmo0*D(TrK6kRA)DMT4h?-fa9fGC?^Y0WWDD93e)uB{H}jTTd*Z6WIA1i4$fG^n5j z7niE{*Z0BY_du#W+0##{s}zs6C{o;nqki;JJk(?h3dC+mwbcWzp}wu7EAs@HaAecx zL5Oaz#=E>?H1Y-Dp=Y4S(CA<7nk~0pXu45_Otg&%46|B!VE0U=($uUrv_2A$b9}e6 znW(86pnP4$7TNifN~Gp`-~y;WWT8Mo3j$8hNx?AL1)<}b#4;pLs*{*cF|6^u#A&i4 zns&{}WTQ!qt=>56Yw)7%?g(q2`quAgmfgXvpOv1`@#!R7FHWHEyUjKfIy0QZ$qEWs z>|KQgE_RL=MONDaPY;DL=#lAUDQHmSmCb1_2Q8!KC2ZLB*<;OVyha(L(Pl)Q&)E?~ zJwt~BzED@zTO>I-3V3FwfXIRJ8joApBC*7L%Q|nzc&^7TUK-#kYtx3w+DO|Iyi>QL7 z2Rmc4xjR6!tdh4TN#~tO8l2YkwTWmz9>`n zj5{Ni&Y0mkLpHM7onOJ2MOFqKm}>rJ3?iXPrHguAnK<>=x*5P6lg}bzc&ubS5X; z#`-BN6uhB=|H4Sa^;lc#Gudg&mSVilAoPl)-S#X}=gVne(km2e!ZNoCB@ak0?Mago zeNy=0Fs$D;FeG67I{eVnXch~EM3fy{uB#ZS;l zXQ*L80Qo?RM~LYH^wrPD+sPr@405nUU@`A-8sVlOVt@YP_Esdh4zIQOzJ7Cj7pe%& zVmZMZcG_?jn9io3Gmrj00aR)*&?GJ|uwHh_3o96&MdNR;|)(@_g;1Q*x+PK zmaHOX=B41P-9i=o*TeH-4Aqh4)RJjgQ4tuh+x41xip+{7vfD}C&iieb&ScGI<`Hb- zO6p96t^3k$`Cw&TDeSId_Q!1@AK6{dbLitp;sbWQ3zsi4nw-9xykY$jk026KBa9J5 z0#$C^#LNm};Y`iK7Dd&Vig?Sw=(p)NzS>49Mp><}E*T>1$Nq){9o3J)aLA)YZ8AXk zw`PJZS4tLHQ5cC+SDu@%O|2SR@V#SRk=WXN9x3E-k(Cd{pYFn`C-hmh@z zW5iB*L@hZdXWCIWjqg;Ff^U9pW!ILM=TQmry?Y{9)!?np)P8(7*J=?|7gnEcm)AIh z7`UI_JzSh0@d)vsg@mFBc^{;<4+iHt)wLjHudRAvIMg-CujRZZZbJABkF7me2=mGq z$`>SRMtme08)Wmgb%p3RE&H35IN(?;KA3IPYIc7S^^~7tIsq8M{GXMqR$*3rh=1Hu zMSj7T|7%x~0|0*wt$)re4glcm$m`+h=V%Sn79@pz=chulhfVNnAvwVq1+|U+}=} Zg@FIlFR(-*Qlvky5+P>vNWTBX{udqJuh;+p delta 5698 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