From 9fb55c3f5aab1aaecb2fea1bcbcbd5dc215417de Mon Sep 17 00:00:00 2001 From: "cyril.tsui" Date: Thu, 27 Jun 2024 16:08:04 +0800 Subject: [PATCH] update report --- .../project/entity/InvoiceRepository.kt | 2 + .../modules/report/service/ReportService.kt | 46 +++++++++++++----- .../modules/report/web/ReportController.kt | 6 ++- .../AR04_Cost and Expense Report v02.xlsx | Bin 12808 -> 12733 bytes ...08_Monthly Work Hours Analysis Report.xlsx | Bin 14716 -> 14715 bytes 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/ffii/tsms/modules/project/entity/InvoiceRepository.kt b/src/main/java/com/ffii/tsms/modules/project/entity/InvoiceRepository.kt index cdedfc4..940f2d2 100644 --- a/src/main/java/com/ffii/tsms/modules/project/entity/InvoiceRepository.kt +++ b/src/main/java/com/ffii/tsms/modules/project/entity/InvoiceRepository.kt @@ -12,4 +12,6 @@ interface InvoiceRepository : AbstractRepository { fun findInvoiceInfoByPaidAmountIsNotNull(): List fun findByInvoiceNo(invoiceNo: String): Invoice + + fun findAllByProjectCodeAndPaidAmountIsNotNull(projectCode: String): List } \ No newline at end of file diff --git a/src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt b/src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt index 82cf016..406c52e 100644 --- a/src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt +++ b/src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt @@ -435,7 +435,8 @@ open class ReportService( val uninvoiceCell = row.createCell(12) uninvoiceCell.apply { cellFormula = - " IF(I${rowNum}<=J${rowNum}, I${rowNum}-L${rowNum}, IF(AND(I${rowNum}>J${rowNum}, J${rowNum}J${rowNum}, J${rowNum}>=L${rowNum}), J${rowNum}-L${rowNum}, 0))) " + " IF(I${rowNum}-L${rowNum}<0, 0, I${rowNum}-L${rowNum})" +// " IF(I${rowNum}<=J${rowNum}, I${rowNum}-L${rowNum}, IF(AND(I${rowNum}>J${rowNum}, J${rowNum}J${rowNum}, J${rowNum}>=L${rowNum}), J${rowNum}-L${rowNum}, 0))) " cellStyle.dataFormat = accountingStyle } @@ -1080,6 +1081,13 @@ open class ReportService( val boldFont = workbook.createFont() boldFont.bold = true boldStyle.setFont(boldFont) + + val projectsStyle = workbook.createCellStyle() + val projectsFont = workbook.createFont() + projectsFont.bold = true + projectsFont.fontName = "Times New Roman" + projectsStyle.setFont(projectsFont) + val daysOfMonth = (1..month.lengthOfMonth()).map { day -> val date = month.withDayOfMonth(day) val formattedDate = date.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")) @@ -1228,7 +1236,7 @@ open class ReportService( projectList.forEachIndexed { index, title -> tempCell = sheet.getRow(7).createCell(columnIndex + index) tempCell.setCellValue(title) - tempCell.cellStyle = boldStyle + tempCell.cellStyle = projectsStyle CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER) CellUtil.setVerticalAlignment(tempCell, VerticalAlignment.CENTER) CellUtil.setCellStyleProperties(tempCell, ThinBorderBottom) @@ -1271,7 +1279,7 @@ open class ReportService( ///////////////////////////////////////////////////////// Leave Hours title //////////////////////////////////////////////////////////////////// tempCell = sheet.getRow(rowIndex).createCell(columnIndex) tempCell.setCellValue("Leave Hours") - tempCell.cellStyle = boldStyle + tempCell.cellStyle = projectsStyle CellUtil.setVerticalAlignment(tempCell, VerticalAlignment.CENTER) CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER) CellUtil.setCellStyleProperties(tempCell, ThinBorderBottom) @@ -1279,8 +1287,10 @@ open class ReportService( columnIndex += 1 tempCell = sheet.getRow(rowIndex).createCell(columnIndex) tempCell.setCellValue("Daily Manhour Spent\n(Excluding Leave Hours)") - tempCell.cellStyle = boldStyle - CellUtil.setAlignment(tempCell, HorizontalAlignment.LEFT) + tempCell.cellStyle = projectsStyle +// CellUtil.setAlignment(tempCell, HorizontalAlignment.LEFT) + CellUtil.setVerticalAlignment(tempCell, VerticalAlignment.CENTER) + CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER) CellUtil.setCellStyleProperties(tempCell, ThinBorderBottom) sheet.addMergedRegion(CellRangeAddress(6, 6, 2, columnIndex)) @@ -1375,7 +1385,7 @@ open class ReportService( rowIndex = 5 columnIndex = 0 - generalCreateReportIndexed(sheet, result, rowIndex, columnIndex) + generalCreateReportIndexed(sheet, result.distinct(), rowIndex, columnIndex) return workbook } @@ -1825,12 +1835,12 @@ open class ReportService( + " (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) as budgetConsumptionRate, " + " (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) as manhourConsumptionRate, " + " CASE " - + " when (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) >= :lowerLimit and (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) <= 1 " - + " or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= :lowerLimit and (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) <= 1 " - + " then 'Potential Overconsumption' " + " when (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) >= 1 " + " or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= 1 " + " then 'Overconsumption' " + + " when (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) >= :lowerLimit and (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) <= 1 " + + " or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= :lowerLimit and (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) <= 1 " + + " then 'Potential Overconsumption' " + " else 'Within Budget' " + " END as status " + " FROM project p " @@ -1884,6 +1894,15 @@ open class ReportService( + " left join salary s2 on s.salaryId = s2.salaryPoint" + " left join team t2 on t2.id = s.teamId" + " )," + + " cte_timesheet_sum as (" + + " Select p.code, sum((IFNULL(t.normalConsumed, 0) + IFNULL(t.otConsumed , 0)) * s2.hourlyRate) as sumManhourExpenditure" + + " from timesheet t" + + " left join project_task pt on pt.id = t.projectTaskId" + + " left join project p ON p.id = pt.project_id" + + " left join staff s on s.id = t.staffId" + + " left join salary s2 on s.salaryId = s2.salaryPoint" + + " group by p.code" + + " )," + " cte_invoice as (" + " select p.code, sum(i.issueAmount) as sumIssuedAmount , sum(i.paidAmount) as sumPaidAmount" + " from invoice i" @@ -1893,10 +1912,11 @@ open class ReportService( + " select p.code, p.description, c.name as client, IFNULL(s2.name, \"N/A\") as subsidiary, concat(t.code, \" - \", t.name) as teamLead," + " IFNULL(cte_ts.normalConsumed, 0) as normalConsumed, IFNULL(cte_ts.otConsumed, 0) as otConsumed, DATE_FORMAT(cte_ts.recordDate, '%Y-%m') as recordDate, " + " IFNULL(cte_ts.salaryPoint, 0) as salaryPoint, " - + " IFNULL(cte_ts.hourlyRate, 0) as hourlyRate, IFNULL(cte_i.sumIssuedAmount, 0) as sumIssuedAmount, IFNULL(cte_i.sumPaidAmount, 0) as sumPaidAmount," + + " IFNULL(cte_ts.hourlyRate, 0) as hourlyRate, IFNULL(cte_i.sumIssuedAmount, 0) as sumIssuedAmount, IFNULL(cte_i.sumPaidAmount, 0) as sumPaidAmount, IFNULL(cte_tss.sumManhourExpenditure, 0) as sumManhourExpenditure," + " s.name, s.staffId, g.code as gradeCode, g.name as gradeName, t2.code as teamCode, t2.name as teamName" + " from project p" + " left join cte_timesheet cte_ts on p.code = cte_ts.code" + + " left join cte_timesheet_sum cte_tss on p.code = cte_tss.code" + " left join customer c on c.id = p.customerId" + " left join tsmsdb.team t on t.teamLead = p.teamLead" + " left join cte_invoice cte_i on cte_i.code = p.code" @@ -1959,6 +1979,9 @@ open class ReportService( if (info["code"] == item["code"] && "subsidiary" !in info) { info["subsidiary"] = item.getValue("subsidiary") } + if (info["manhourExpenditure"] != item.getValue("sumManhourExpenditure")) { + info["manhourExpenditure"] = item.getValue("sumManhourExpenditure") + } if (info["description"] != item.getValue("description")) { info["description"] = item.getValue("description") } @@ -2319,7 +2342,8 @@ open class ReportService( } val totalManhourECell = totalManhourERow.getCell(1) ?: totalManhourERow.createCell(1) totalManhourECell.apply { - cellFormula = "SUM(${lastColumnIndex}${startRow}:${lastColumnIndex}${startRow + staffInfoList.size})" +// cellFormula = "SUM(${lastColumnIndex}${startRow}:${lastColumnIndex}${startRow + staffInfoList.size})" + setCellValue(info.getValue("manhourExpenditure") as Double) cellStyle.dataFormat = accountingStyle } CellUtil.setCellStyleProperty(totalManhourETitleCell, "borderBottom", BorderStyle.THIN) diff --git a/src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt b/src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt index f84307e..1c312f0 100644 --- a/src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt +++ b/src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt @@ -34,6 +34,8 @@ import java.time.format.DateTimeFormatter import com.ffii.tsms.modules.project.entity.Project import com.ffii.tsms.modules.project.service.SubsidiaryService import com.ffii.tsms.modules.report.web.model.* +import org.apache.commons.logging.Log +import org.apache.commons.logging.LogFactory import org.springframework.data.domain.Example import org.springframework.data.domain.ExampleMatcher @@ -58,6 +60,7 @@ class ReportController( private val subsidiaryRepository: SubsidiaryRepository ) { + private val logger: Log = LogFactory.getLog(javaClass) @PostMapping("/fetchProjectsFinancialStatusReport") @Throws(ServletRequestBindingException::class, IOException::class) fun getFinancialStatusReport(@RequestBody @Valid request: FinancialStatusReportRequest): ResponseEntity { @@ -76,7 +79,8 @@ class ReportController( val project = projectRepository.findById(request.projectId).orElseThrow() val projectTasks = projectTaskRepository.findAllByProject(project) - val invoices = invoiceService.findAllByProjectAndPaidAmountIsNotNull(project) +// val invoices = invoiceService.findAllByProjectAndPaidAmountIsNotNull(project) + val invoices = invoiceRepository.findAllByProjectCodeAndPaidAmountIsNotNull(project.code!!) val timesheets = timesheetRepository.findAllByProjectTaskIn(projectTasks) val reportResult: ByteArray = excelReportService.generateProjectCashFlowReport(project, invoices, timesheets, request.dateType) diff --git a/src/main/resources/templates/report/AR04_Cost and Expense Report v02.xlsx b/src/main/resources/templates/report/AR04_Cost and Expense Report v02.xlsx index 8f971d5d354e78f2f97e801e1a5f0ab30751ad09..6dea4f8e97cf4db487ef9860577c55da4e429415 100644 GIT binary patch delta 4611 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 delta 4664 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 GbNPR*&#>?S diff --git a/src/main/resources/templates/report/AR08_Monthly Work Hours Analysis Report.xlsx b/src/main/resources/templates/report/AR08_Monthly Work Hours Analysis Report.xlsx index c471a6a4b6f33e637715ceb29ed99533993071f6..29dbffd5e6763981f01b55acf9964d08585a239d 100644 GIT binary patch delta 5743 zcmaJ_cQ~Bg_SGXoh^V92C=tP8d|6ENuCpHq^#OwKC1ADky8A z<3+5{M@>GULosxYI%mOzZ?CLU;j(Gkd#`onj2>5!t4z|Q;_v~eR7xPWbxy3>+M!EL zi;A=d&g-V6#qFd0(DY@Z1KCjO8xnuwcFAiIp5k{)Zt1^DHLk$F^_G=nZ7_SRPJ@5c zXHJ_v_tlhUpecTL7PW30GM_FT0X;YJQW__0YO9xfdwUnk(1}6jd;Q9>UbnAIEqSKX zZb*yc;a9AG)+jKF#6(&910wd5EkK`XOML>YxnL~zVzSm`N!G}pXlHTF%CR`|52vhI z{&OpHm4jsbYoT`@t8V|6@6RoVf%|gaxnJxWV;ZZs(yWvo=E>DS_zA ze8bcYicE?Zi9tsfb}{eq=Z~aYAL4yD^#$WMH*p9iL+SgVNWp10;x@T}D&Rai$*L<> zBEB=gnNw*AP$S`&@ZOt}V>g?Xo~w4#Y*^x{I_Y^DTz&bp*lms1kFD#Dj!)gDiTj}E zBfsLku_*=Ecc}BP2G1#*(AF7|mUNB4HMS|aH++j|Uh(YkxIz-NY7Hj3958#l=>aq0ZtenAw>;?c{ zZGTHECmH}|fMpJSUu`*&!(TnI&1>=>TN7kwIy(Q>A>4|;b0etK%Ntrczcm;lr7(KP z&1ESs&$$Y?wtt^wxRIPDelE}9%)cY*WHccO{z^AH@B@w~936$tc z`EdgWhf5v@hYknsCINsiky1kO_{M3fB_1{)(G6aVZvefS9wakwFWc?lk$SpJl?2Dh zj0%vE;KVZ8V8h@MU6*^W=sO`Xvf~D(KOE&$lE?=Q!(}}*L8)fq?l8-j>a_bwETuAt z+yj`~7#&13{vc`>dhe6urtG~NE%Z<3LD(8W|m0n2L9rtazRg&iiLC$m)1EQ}2 z)^a4thC=fntL`S8+D-4n;RI#cuBP-XeIJzeT}~FQ87ZWb^)?l5M8Fkmot`iRsH*M2 zBS*ujnQZoCY$kE){SeUp7a1Z4KC!Qh_6nN-C3&6hX>)3#X7+~SW|o4TJmxEb0Pc>@ zAsZ`8dP8LbruD&&%xIbAhtslsG66XCanDXf>FTs^;@dpfrK)sv4!_gbtm8#*C52v3 zbg>&r9+Ru27b6w5SvpS!PJ@8;<}z=@WN*y#O|V&Mo!B={E80SxeVaWFS(VA4ju}<3 zgH6)!{r>)h>M6GdPyekQ~iA1-Z$g)@f!nv z77$a5s4Ad4{z=f-NCQjXnrV?yEJW#3W=EP5FnU;S5vZt`=)U4=WL^4FEe-@nOBWF_ z+eD67{HY7j@ONdKt)Dc@E>*2lr00?jP)1!#&)0 zMl%WLKiCns3^na8N|M-}4JL@RBL(SYT4-1UnYQD4iE2?ld-BN0~&6k3&?!gj`NdV7KPr|3LOy0#ojq|2NDt_ zDcc%+y1I$+9E6?+Nh-9S?yr_bFP>WIvBWEo=jC-&uVcoKDJA7v&AmNuTpaDspYJbr z2ly9{ zhGor`-dg#y-r@`o!3`wLOru)eFKGE$ee`~r@7E!wF%NSYhk>5`^lk2CLYhM{0IQ1& z%Nq2rVW*U?AhVvNUlYcS3(Lu;kLP>(F7`;(<=rcOE0da%g!XE;uVXoGAOaDcreZ`U z6p)vwIpYYa2$8fZc5~XZoD3jiEVV{q6c2@3;gTkbj#7dZeyi3_^&o6o(UF5pWo))} z`$M40=-`UACK)|YMezfa_B%o|jS*20a#zd<-v0tokZq_U);w7uC&J)Dx3M)B-P%k8 zBSo;OxDxXm*PsI_l4B*xU|5vYccYulb2ADH>`MmVkwET> zMH>A`0}Sx~+q`^YX(D7QIqdaM2*-vdQvlGqG%UE?fQ&6&wgl#_O*Up<=itiYgiY`S zsZF-5+htIuTrCsgft^&i7#8-7MdyD(TLr8H>99C#!TEE&Kow0ceJmrOidd$5CSZUb zTgt0ypo-M!eH3rfH8&?klH{%^@z4gOQLYAlb6 zm=J6!br2=nRLWB!p2IT_vr%mCX)ScHR)=~bJey&gr+rAVF71eMa zN-pf*WD6CnV?y?-HEhWYeeT6J<)etCEmR_kLZ+c?3BVqw+MfbYE<<8*>L?2728Sg8 zUS81peCUT>?*OKk&32TX)1?Uq@D*G)<0L` zoGD{OfwYKu=~aE-dJ}&Bp05p54-%n{{qMkQ(+zBXuKEaUDE&(q1XQ5-s*4IhXg)C` zC&$4*R3L*B2)PoBa4|dRZ^~ExVJpCPTTZ3`*1>g@hM%j3YfR1*2ph5xOPbhe%r(iD zpI<5T(6xN{(+g}1gEu&28vaH258nWF4|4HR) zGWlAN3{YhYm3tL*xiqdsQ@#qqL1gn%V#0r;p#K%-N<4x{`PjdVlQ?=C@60xkccOBWloQzJOc+sLOUwk=~5X`{|7v&G!i(<>-aXoz|TOZe}co1 z^{=v8qUAhx6mvc9023z0h;*nq*r{Ls9*J*j+1uisdkPTFA+?;oW-`~`^CnNN|RGtVa&yX#kP58$QL*=blo-M?!KDS zmJMY)!@9HhU1y1BS-R>vW3P<0cdaa$R^^r&2a>MSeLi6c%lE{ z0()w$pQP=(2K^dDW|2>bgHy+VgG2V$QPu|>=`Vij6AY zxl17%+chaPGd|BKv*5+wP1-JKku2I%*Sk(d!XW`r>nTJ};8eh5C>Gj}=RV;3GkzEh7B0)d)FDccJs8f7s5J|b;sQG4DJt4 z=y(+avR2By!fu;tI`_&I$r}MCb!-XvQ4Kzr`I6#S=~+8Ig&)?lQpZc&;h zl`?_RekNy3$|E6Sc3Jk90!5?|O(S>Kkei1QU9V)2<#?h=y=Id2c@G*uLialxGg zU+A}tcs&D*_5{baynrX`?^==d$CS;3;w?f0x=`kv zYrBw=b)3Ul9l9eMBCW_G=N>{L9nF_($Z&C9_E>U!M1Z{2FdNft>wpyFkQvw*i1My) zS4~^Kcht-w50{;!p*D?eR*z95Q^9pYPYT(bTC1$#`5m4Tsz;4z=0)o)ZtT&#B*ZRW zVm|CyeL2S{eKr?Y&z${pZ-S83M^MH>1Mhc<%JeVqsv3en7N5(S&NnJK$|Hn$vQzHr z&}G(X+&A9ic@u}bWizAmaVn$5Bmcb%Wf1`#@vS(OkJ)UbDXgs_-Vds*eQ+JyEO=jz z6qS(YOW6zIO^=n2gc>IVb0xZNaB1<9@Cs6iI*$6DjGQBhwe z`0o{m)Cnn0Tn`O4qV|m7a%FbtJ*)8o#n0z7T%TzmZYHsQL3u`_oDg+y&_6KAU=}dC z&d$uXu+I*sraEfSk;@Z*78dz#0Y(O!yjSFwTkDq)aqY*aP}XhcENQgghu4?Ol03W( zqyyEIrE|ZcH8asgzHVvP;w|4mqvzglPVyD{3)XLUikKT<#wm9Etvz!v(T>eQaiQWA zNvdEs5$zzAXD3nvC(*+EQl3;MGMU%Q<5-CNPhGFUW)ny@9xy&}W(G!Kv`V6;*CjCs-T=l2Y%*Nyf+m@uk`872dvP*@98VnEJd z??_Q?4?hiYq`_BFX6Z<_JUoLKV|C#w@%yTVkk#r7FFfUFuC@xmA`je~#^Omt~k|hgS z*|wO|Shokv=ZP}5Wdj&PZQI&0qCt)zuPqqjk=}@r#pq9}p`(zIeUFhkSYzDz!Tgc_ z&gJp(QMC5GuE(9evNJvwq4}ilZsm`j6d?{QMnH^q`R^XQv&n?DX+7bh=d0ANvpWD| za15WQfbI_Acjqqicg??N%*vJDWy;X0$+|gL>t)$c5HJ{3S4lPt%{M!tkQG&jTi^P! zKc*n#{qqbTu&74*?yhlLcLwh=yEOL6Gv6ifY-Cj2ni^3;@Nqf~K?H3Zq>Cx2y+E`9 z0;<)u=dYPz;X{h8kw>>z(ofAj-hQ^s{Eh!ip4d#MWo&@GDUz+n@y4#xn1x0S89~VG z8vcauR?WP#ocT9pDhvutoSu&mWg0aOF_(ZPjvcwPSeQ*KF1NI;iajsgXleRvGq+6> zWf>d^|7ubay-`2MNjF=2z2P9z>@m{!lJNIEhaXq$4Z`)9bt&C?0wHc(=wr7oRw~%e zwNva>n<^Z_u0^uBHbxTR;J&4I@HU-G9d&Q0BTox`*TF91SG&ACv#v>51!?>HN2Zme zJ-3u_c`R=r4(Wpg#OEmq$A!2anez7;+@Pucar!RJZNLqGq;%Xmn}8u8wJvRwlqq|Z z%5IR{K#1W4_G7+AoZ1KC0zG^ra?yVnc3XL+39pyHht&VQ0l6wziA0|D=a)1&#iyiP zM)}!2UQ~;DHTa-O1@eRba#O8uu9v0p-(LzGOEFH};g7Z*6*UxD7i)z+$295-o`X~n zEv8LY$gs@yg@U1P)hP}J6GggvJL;&>pc4^F)j8ia z(~GRu2jfXSM9bG>o!By??Tx#20D{iS@-2g&!~Q|52^)pGfo-S&pbggGBYGZSM> z6la4mkk~VZD{0}9Qa9^UM5OSq|GD*rkBaNzLg4HY0u29twS?V2|NLsoRUCqW=VA`p&lep0w5_!rAHMP!9(NPR6+}FsHs&G2qM+i;1BENc4WhD=9L214O}+3 zB_n$yJW;pw{#O*wgkp z7bAcj6t@Sj|3DnOoTY=4OUH2I=uLde%BZu?8@irQmfhDgq-xc(8o2#ITrmHy_Pf+@ zdb9LJ%T79X*i^edl-IX*P=Qk-i#^4MsmxW=lIjiLikPRSX8l4hoO!uhd;|e|i{&N9 z18{s3&9)nJ#?xOkxG^{N{X82U7TW?wEa+<&`^hVOC2kfcI5vA^Yw9R)m+d)Sonb*7 zwu49DU>w3 zFi`GVLg_082@a#BW?la;FF$Zcd%sR9EieM~-d)nfmGL^*O^n&P&U4ZFE>4q_WKI4n zdiR&0M#13G?H~rWMW$iT3 !F9dDdvxa21@g+Z4j2xvoCHqH!O&@Fiq^4V~xw5Ue zF1N3LZbDqWyPut2`z$R6=G-M^26v_3j+P;I_1Hz!lZp#2`)x|W#&1zjJv?~4e;X(v z0eh$vzFvt?&|PA^A}TkX;)xp8ouJp=IPP~kdxPrK^Ly7(6}?%y84 ztQ&IAh?jcwNZK&w$9Q)}uf$io_V;xiWu1TA$7tM>2Z!&iXQf(@biRB;eSb2T&x451 zQ~GU`AdT&OLsF$w)9oo8d-c7_%*v;L;xAw+)gmDBt*UARzhI6g@dl`<3jAg8Vd%TS zn9xI)#s)~T01kI2j|LGnIGb#kZT`rF?WO#c!gkM#fZqI~_H$m-mDN|QlwLpSBa;=$C53!z$gMLNS7CvgFAKF zhdY{x)kH&H8HUsRsx~fkr(jbKQZuytiUi`ga9_`)3F_qt+L?Nd)p0E28|SepHN?|Q zzn<@&kkN?}td=n2;Wt=8+z%F2zi ziyP^We`uFKONLF2GX>eEOo#bc-YC;B1jNgDFTT0W`z(*0fu!au7Qrg6CU$O%rWVlJ zJu))|?!|leb1#qrILgqAg!elZVvRa_3ZF;VrIj@>T`4pk|IrA@qer;nFKNHTvVMrh_3Wy4w@k zu^sxm?e(N8RJ;xXE6>Or7DyzI=ToYQP1eZ<_j(Z6u44@rK(-c%*Iu#4sBsTm5iutoNF zuv$N=;NE$*7DgTEp3TA2`{;Hw)g8CSp1tRt^~}=G2=fjECzk{XFG>3Z5x(Xghc(M5 znJ2H`b$__C)a3%<8oP1cmKmzw-alGqM|eA5>yZ);&djpE*Uq0MB$>5&?I6|KhXDfJ z+@N-bn;W0J{klalDrGB zQ|8tDAOTqgDGIqfMjpzQAIkLsh?9BXCgA5hJZE`4kLd<^4NpP#T?P3E2mBnKn!1bh zzmW_kyy*@`oGikwpCqkfmghjumr|szk>dx;U*nl2RF|a0LNQ74#m8=_!51Fg7mnGj2DWv z;>4%Dv{me9OnWaRhDSDN1CotKkZv_p?3j-yk(S3v1{<~FlL5|~{Bd2~ZUl^Z5=Ck7 z{HV|Q0&3U;`R7wW0|XwwmLFq3nU3py@b7Qo*ZF+O-Ul!VO&cJ@_1z}tA5%BK^6N?S z>cOM(xkuM=rw{6$6&xYl?pni{j)uj5z8rbH=+BJD9uW*iV0-zJAHc7*wwI^k4|U%9 zx5_PY<+FC}7b+*~+zWfpnpcUH-mt?5po<<^+a`BEw!NV;3GN#rnR2pHmUZ_x9JyZh zQ)L!byEV$1SN%H575LRg^@!keG@>Qct?RNJ+(yL@mX=K|w!5+pVnRl!@=!u4S>_c) zZgZ4AN~9jWY5?&2q}3=Y=Mh-1l9~!lyh- zO{LeD@K%&>s-q-i$#NMZ%F6t=oKe7o;pt+L1C1zxXjFw`B`C+fwbr)e&U79*;7416AcW3tYYzW6>05KCY8T#@ zqM7_xP*klPWnRkexCLe`=t@yz^^$I$X(mcapPkdBkl7gC-`V~DhDZWq8k=%sUg?<6 zl~4_(4pvB{b}f*KZVl7}N|OoxF&{!A$bc2z?h2y_bMX#E4yR z(Qk{gB*a79VTHw^{So4smScCsf4)O5q{s|OReovfI9*AyH%Hll4jW8D_BYFCsj+Cb z-}OF0uQe2TOrOz;aZhLH_mk?!RsJOgD#5iN+{4N=Qzf((7jFQR81!gXP}JD-nyg1p zS5l(&7;9(gE?2Q9`%N*Xl&`XTY=K#&b!-9b-+Vw$$k#8o-@plWL-HG?5NP08r><+)y?Zf|qxuYOL zHlY;9jYHwUkYB7?5Gc#Gs=@QbR!2!#k97=Vi1v!m9O&!3TtMh?rKQ9g?3WtSkX1q} zl`=8o`*inkro_I-!HNG40B|R7l_w^RC~giaM*kHwc`F7532$Qgu)t#NOVLx=E@*Ap ze#A-~$NmE%LqU-e$C3Yl@K8{w#Bu09APf`~EP-JW%UKHLCff-89vjm8Irie%V}DQR z5SR)a-|d(TzUc`1uyz~aeZ%tW&8`)%GhE`lNR4D^;+%=ZL5ASj)wTa=&0Wr)S9d2( zSIIXObpi`D9o$Se6&=3(Sde=kb6vloT68FpzhNG7f+&1D6^$NyN#rbKev&L9yH{e0 zTw1%6bM`}4-2w3apWh+BKSr8%sQYmM5nFN3DliCyU;u%L{``IQ_6cx(;*I`!T{2ya zUsR##y?eqKNu{A*_0hCdthG&6jZ`gXdRgJ_tpxs*{Sry>7so2vcog^?kbn$X`KK3R zcqc*^Q;Bv?DY8#Ltkj4$3E$jI0EK{Ac>sgDNvxf?)BS?JzxTB z%$#AS1?$0zTf602=-eG9l-T%f;JkLUovz~)^fH(V$N>_T2tc*ZgGyD6|I)YtY zT`&>kTxWitd!tj4kcSK4xGfu$pp&SWZoi#-2h&27F~u|1{jIN&3DH12x$a7Gx_dRu zbAM0bOM3b%a-S&Z#kw{hbU5UJFwX-x9@zJfa`xjQ_={FoXd`>(2OU-BvT?3e4b@df zMyFwzAL4|TzBf=`yPN#>YIkAz36wQNTL;m2c(-WGx%?HCv{WtN2{Wv*u%6(Qtlg{i zp;Q8?IE=p)(TG#(R|*v^QV*wzqr74sPz?Xl=t;Wf$Wlfm)?ZuoklJ=y2reML^!4rh z({ZkRYpDFn7k}H2wCl2yuFz*XDxmE-T}`{+u0io=?jo-s*BMTard| zMlAfMvyAP%c9$Z6Gd}I0)N|v(c4A=*3Z(F*oT}%H3&Z6)7tw3gkw z5zl?8PTEkffAG+ji=BH!*$t}Al9S1T&Bd0<7VDop#DdQW`2Xb24I5FQP=+TiOs#Q* z&^vCfnPEjSjCMzY4bJcecxA!HLZQM-ZKLh}2IXKDkMu$AFx*JoA(n)E7Q!^#XNX_e zreqV~T;#S!zblnMFld4$f$VFYicDRT^OAt4p}}2s4L!Ahl42p~iofiYJiM#u;PGVn zr`r3URVMfW!tC#2Z3H|_uSH0+OAcGBY#?f-WqR40kd{0c(bM-@M|GwnzM$F6uWi=O z?|q@VqZ zS=S#((lw1N$S18nq~8?m;?q0kc%+*~f8c0S`tl3*v|%N~*T!u+y+sp-JEh^q`+@V( zcSkJ`funVty6m$Y6EYxrch;W8Uq|#L?0^cV;>=%_x8Wddt2oCr9D@1v!fKbyVwY4P z2u!~FrDa3dk0WVJpPKc;BbhBeV`JlHGdcyhI-5euap2aE?}&48c@tWcSzSffNoX@! z+S0izHnzUVN8+?-seqyRw0*1aW;N5iu+!yl0vtF74a8)7hx`BUj3 zp^MJNX8LTW&(&MTnI-bI+)^qg=S0jKVj@Eyq~-Tad+*VlOoVN3KVS8f*r@Wyq@&*e zj36ogb=*NL-=FusBEGN4CPKVP*7NYXNx)=Pu9&QF*kjD*qh@fHzIG`Jx%<%80N&%u z&2MFQbdAyXA>Vqsbl#;Ma|)7K_Q{1eJI-~eB?xn<^`fW$jlZbkZeMke!TyoPP|?R? znOEjqrdUr+Uy8e8TzA7<##_Qdr;x8SL0!qqq71bzyRh$hFyb7 z7VbxAB*b(-YHJIg_+V&3eP~12{aoSODC>ZFWwpNIsi`hGA(MEdnX^Le3cu7%MlmL3 zlOIPM0l3575UkaNCB%sV+;@o(q=`O^xWXB=xV^sV8mXtP!0Cbw(!WwltG4n~& zZSa!4cDN71N(y7QBG+9Nb|NZqKn^s{sm1w2o)l|Eb(n1XML5yxr94r)&3&`#=jjt) zXteiVP#QG2Emjl|(XGh6JIpK3`Bqh;dsRbId=JiVi(TRJAfVpbE4X2XLl5AiW_m#)>Kz3%ZYxlkw5$D+o*S)-#uZR@{ukJFAmP4u6XbDcV((o2Ry_U z5aQcAPY+pF|7K<51^0a1SfK_(P?l2<3KuhUzb;Zj5TVbIG9VJfO{u~Xn0SAm`DT0& z)5ZwOV1WoQ{C&103j)!gHqw7xb%Yrcgmf805Yh}d4JqpQ>91=l<28hn{y%r%zutmC c8BIqJT#P@}%(xOa#PH3~mtez|7ekx;56=+SEdT%j