Fixed Hourly MIS

This commit is contained in:
2026-08-12 15:40:43 +05:30
parent 61bea5fb6e
commit a757799724
24 changed files with 996 additions and 30 deletions

View File

@@ -0,0 +1,49 @@
package lib.models;
import java.time.LocalDate;
import java.util.Arrays;
public final class HourlyMisRecord {
private final long userId;
private final String displayName;
private final LocalDate receivedDate;
private final int[] hours = new int[24];
public HourlyMisRecord(long userId, String displayName, LocalDate receivedDate) {
this.userId = userId;
this.displayName = displayName;
this.receivedDate = receivedDate;
}
public long getUserId() { return userId; }
public String getDisplayName() { return displayName; }
public LocalDate getReceivedDate() { return receivedDate; }
public int getHour(int hour) { return hours[hour]; }
public void addCases(int hour, int cases) { hours[hour] += cases; }
public int getTotal() { return Arrays.stream(hours).sum(); }
public int getHour00() { return hours[0]; }
public int getHour01() { return hours[1]; }
public int getHour02() { return hours[2]; }
public int getHour03() { return hours[3]; }
public int getHour04() { return hours[4]; }
public int getHour05() { return hours[5]; }
public int getHour06() { return hours[6]; }
public int getHour07() { return hours[7]; }
public int getHour08() { return hours[8]; }
public int getHour09() { return hours[9]; }
public int getHour10() { return hours[10]; }
public int getHour11() { return hours[11]; }
public int getHour12() { return hours[12]; }
public int getHour13() { return hours[13]; }
public int getHour14() { return hours[14]; }
public int getHour15() { return hours[15]; }
public int getHour16() { return hours[16]; }
public int getHour17() { return hours[17]; }
public int getHour18() { return hours[18]; }
public int getHour19() { return hours[19]; }
public int getHour20() { return hours[20]; }
public int getHour21() { return hours[21]; }
public int getHour22() { return hours[22]; }
public int getHour23() { return hours[23]; }
}

View File

@@ -0,0 +1,6 @@
package lib.models;
public record ReportColumnDefinition(
String columnKey, String label, int displayOrder, String alignment,
int width, boolean visible, boolean totalled) {
}

View File

@@ -0,0 +1,8 @@
package lib.models;
import java.util.List;
public record ReportDefinition(
String reportKey, String title, boolean hideLeadingZeroColumns,
List<ReportColumnDefinition> columns) {
}

View File

@@ -10,7 +10,7 @@
<link href="/matrix/css/matrix-v2.css?v=6" rel="stylesheet"> <link href="/matrix/css/matrix-v2.css?v=6" rel="stylesheet">
<link href="/matrix/css/matrix-shell-v2.css?v=7" rel="stylesheet"> <link href="/matrix/css/matrix-shell-v2.css?v=7" rel="stylesheet">
<link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet"> <link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet">
<link href="/matrix/css/dedupe-workflows-v1.css?v=3" rel="stylesheet"> <link href="/matrix/css/dedupe-workflows-v1.css?v=12" rel="stylesheet">
<link href="/matrix/css/matrix-frame-dialog.css?v=6" rel="stylesheet"> <link href="/matrix/css/matrix-frame-dialog.css?v=6" rel="stylesheet">
<link href="/matrix/css/matrix-theme-v2.css?v=4" rel="stylesheet"> <link href="/matrix/css/matrix-theme-v2.css?v=4" rel="stylesheet">
<script src="/matrix/js/bootstrap-5.3.8.bundle.min.js" defer></script> <script src="/matrix/js/bootstrap-5.3.8.bundle.min.js" defer></script>
@@ -23,7 +23,7 @@
data-context-path="${pageContext.request.contextPath}"> data-context-path="${pageContext.request.contextPath}">
<div id="PageFrame"> <div id="PageFrame">
<%@ include file="/WEB-INF/app/fragments/app-shell-header.jspf" %> <%@ include file="/WEB-INF/app/fragments/app-shell-header.jspf" %>
<main class="matrix-tool-workspace__content"> <main id="formcontainer" class="matrix-tool-workspace__content">
<form:form method="post" action="${pageContext.request.contextPath}/ver/dedupecaselist" <form:form method="post" action="${pageContext.request.contextPath}/ver/dedupecaselist"
id="dedupeWorkspace" modelAttribute="dedupeWorkspace"> id="dedupeWorkspace" modelAttribute="dedupeWorkspace">
<section class="matrix-dedupe-worklist"> <section class="matrix-dedupe-worklist">

View File

@@ -27,7 +27,7 @@
<link href="/matrix/css/matrix-v2.css?v=6" rel="stylesheet" type="text/css" /> <link href="/matrix/css/matrix-v2.css?v=6" rel="stylesheet" type="text/css" />
<link href="/matrix/css/matrix-shell-v2.css?v=7" rel="stylesheet" type="text/css" /> <link href="/matrix/css/matrix-shell-v2.css?v=7" rel="stylesheet" type="text/css" />
<link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" /> <link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" />
<link href="/matrix/css/dedupe-workflows-v1.css?v=8" rel="stylesheet" type="text/css" /> <link href="/matrix/css/dedupe-workflows-v1.css?v=12" rel="stylesheet" type="text/css" />
<script src="/matrix/js/bootstrap-5.3.8.bundle.min.js" defer></script> <script src="/matrix/js/bootstrap-5.3.8.bundle.min.js" defer></script>
<script src="/matrix/js/matrix-shell-v2.js" defer></script> <script src="/matrix/js/matrix-shell-v2.js" defer></script>
<link href="/matrix/css/matrix-frame-dialog.css?v=6" rel="stylesheet" type="text/css" /> <link href="/matrix/css/matrix-frame-dialog.css?v=6" rel="stylesheet" type="text/css" />

View File

@@ -212,7 +212,7 @@
<div id="FormPanel2" class="FormPanel"> <div id="FormPanel2" class="FormPanel">
<table align="center" class="matrix-form-controls" style="width:100%"> <table align="center" class="matrix-form-controls" style="width:100%">
<tr> <tr>
<td><form:textarea path="earremarks" style="width:98%" rows="9" readonly="true" ></form:textarea></td> <td><form:textarea path="earremarks" style="width:98%" rows="8" readonly="true" ></form:textarea></td>
</tr> </tr>
</table> </table>
</div> </div>
@@ -232,7 +232,7 @@
<div id="FormPanel2" class="FormPanel"> <div id="FormPanel2" class="FormPanel">
<table align="center" class="matrix-form-controls" style="width:100%"> <table align="center" class="matrix-form-controls" style="width:100%">
<tr> <tr>
<td><form:textarea path="negremarks" style="width:98%" rows="9" readonly="true" ></form:textarea></td> <td><form:textarea path="negremarks" style="width:98%" rows="8" readonly="true" ></form:textarea></td>
</tr> </tr>
</table> </table>
</div> </div>

View File

@@ -219,7 +219,7 @@
DOB DOB
</div> </div>
<div class="inputcontainer"> <div class="inputcontainer">
<input type="text" id="dob" name="dob" maxlength="10" style="width:80px" value="" onkeydown="return addSlashes(this,event)" onblur="validate(this,'f','Date')" /> <input type="text" id="dob" name="dob" class="matrix-date-input" data-date-mode="date" maxlength="10" style="width:80px" value="" autocomplete="off" inputmode="numeric" placeholder="DD/MM/YYYY" onkeydown="return addSlashes(this,event)" onblur="validate(this,'f','Date')" />
</div> </div>
</div> </div>
<div class="widget"> <div class="widget">

View File

@@ -27,11 +27,13 @@
<link href="/matrix/css/matrix-shell-v2.css?v=7" rel="stylesheet" type="text/css" /> <link href="/matrix/css/matrix-shell-v2.css?v=7" rel="stylesheet" type="text/css" />
<link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" /> <link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" />
<link href="/matrix/css/mis-filter-v4.css?v=1" rel="stylesheet" type="text/css" /> <link href="/matrix/css/mis-filter-v4.css?v=1" rel="stylesheet" type="text/css" />
<link href="/matrix/css/date-time-input-v1.css?v=1" rel="stylesheet" type="text/css" />
<script src="/matrix/js/bootstrap-5.3.8.bundle.min.js" defer></script> <script src="/matrix/js/bootstrap-5.3.8.bundle.min.js" defer></script>
<script src="/matrix/js/matrix-shell-v2.js" defer></script> <script src="/matrix/js/matrix-shell-v2.js" defer></script>
<link href="/matrix/css/matrix-frame-dialog.css?v=6" rel="stylesheet" type="text/css" /> <link href="/matrix/css/matrix-frame-dialog.css?v=6" rel="stylesheet" type="text/css" />
<script src="/matrix/js/matrix-frame-dialog.js?v=2" defer></script> <script src="/matrix/js/matrix-frame-dialog.js?v=2" defer></script>
<script src="/matrix/js/matrix-accessibility-v1.js?v=1" defer></script> <script src="/matrix/js/matrix-accessibility-v1.js?v=1" defer></script>
<script src="/matrix/js/lib/date-time-input-v1.js?v=1" defer></script>
<link href="/matrix/css/matrix-theme-v2.css?v=4" rel="stylesheet" type="text/css" /> <link href="/matrix/css/matrix-theme-v2.css?v=4" rel="stylesheet" type="text/css" />
</head> </head>

View File

@@ -17,15 +17,24 @@
<link href="/matrix/css/bootstrap-5.3.8.min.css" rel="stylesheet" type="text/css" /> <link href="/matrix/css/bootstrap-5.3.8.min.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/matrix-v2.css?v=6" rel="stylesheet" type="text/css" /> <link href="/matrix/css/matrix-v2.css?v=6" rel="stylesheet" type="text/css" />
<link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" /> <link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" />
<link href="/matrix/css/mis-output-v1.css?v=1" rel="stylesheet" type="text/css" /> <link href="/matrix/css/mis-output-v1.css?v=7" rel="stylesheet" type="text/css" />
<title>Cygnus 1.0 | ${filter.title }</title> <title>Cygnus 1.0 | ${filter.title }</title>
<script src="/matrix/js/matrix-accessibility-v1.js?v=1" defer></script> <script src="/matrix/js/matrix-accessibility-v1.js?v=1" defer></script>
<link href="/matrix/css/matrix-theme-v2.css?v=4" rel="stylesheet" type="text/css" /> <link href="/matrix/css/matrix-theme-v2.css?v=4" rel="stylesheet" type="text/css" />
</head> </head>
<body class="matrix-v2 matrix-mis-output"> <body class="matrix-v2 matrix-mis-output">
<form:form method="post" name="filter" id="filter" modelAttribute="filter" > <form:form method="post" name="filter" id="filter" modelAttribute="filter" >
${filter.html} <c:if test="${hourlyJasperReport}">
<div class="matrix-report-actions">
<button type="submit" class="btn btn-primary btn-sm" formaction="${pageContext.request.contextPath}/ver/dtmis/xlsx">Export XLSX</button>
<button type="submit" class="btn btn-outline-primary btn-sm" formaction="${pageContext.request.contextPath}/ver/dtmis/pdf">Export PDF</button>
<button type="submit" class="btn btn-outline-primary btn-sm" formaction="${pageContext.request.contextPath}/ver/dtmis/csv">Export CSV</button>
</div>
</c:if>
<div class="matrix-report-scroll">
${filter.html}
</div>
<input type="hidden" id="invalidfields" value="0" /> <input type="hidden" id="invalidfields" value="0" />
<form:hidden path="qid" /> <form:hidden path="qid" />
<form:hidden path="title" /> <form:hidden path="title" />

View File

@@ -1,6 +1,11 @@
.matrix-tool-workspace.matrix-dedupe-workflow {
padding: 0;
}
.matrix-dedupe-workflow .matrix-tool-workspace__content { .matrix-dedupe-workflow .matrix-tool-workspace__content {
width: calc(100% - 24px) !important; width: calc(100% - 24px) !important;
max-width: 1380px !important; max-width: 1380px !important;
margin: 10px auto 0 !important;
} }
.matrix-dedupe-workflow .title { .matrix-dedupe-workflow .title {
@@ -109,9 +114,10 @@
} }
.matrix-dedupe-worklist__table-wrap { .matrix-dedupe-worklist__table-wrap {
margin: 8px; margin: 0;
border: 1px solid #c3d0da; border: 0;
border-radius: 4px; border-top: 1px solid #c3d0da;
border-radius: 0;
} }
.matrix-dedupe-worklist__table-wrap thead th { .matrix-dedupe-worklist__table-wrap thead th {

View File

@@ -10,7 +10,7 @@
.matrix-mis-output form { .matrix-mis-output form {
width: 100%; width: 100%;
max-width: 1600px; max-width: none;
margin: 0 auto; margin: 0 auto;
padding: 12px; padding: 12px;
overflow: auto; overflow: auto;
@@ -129,3 +129,43 @@
box-shadow: none; box-shadow: none;
} }
} }
.matrix-report-actions {
display: flex;
justify-content: flex-end;
gap: 6px;
margin: 0 0 0.5rem;
}
.matrix-report-scroll {
width: 100%;
max-width: 100%;
overflow-x: auto;
overflow-y: hidden;
padding-bottom: 6px;
}
.matrix-report-scroll .jrPage {
max-width: none;
}
.matrix-mis-output .jrPage {
margin: 0 auto;
background: #f7fafc;
border: 1px solid #9fb2c3;
box-shadow: 0 2px 8px rgba(38, 66, 89, 0.12);
}
.hourly-mis { width: 100%; box-sizing: border-box; padding: 18px; background: #f7fafc; border: 1px solid #9fb2c3; }
.hourly-mis__header { text-align: center; }
.hourly-mis__header h1 { margin: 0; font-size: 18px; font-weight: 700; }
.hourly-mis__header h2 { margin: 3px 0; font-size: 14px; font-weight: 700; }
.hourly-mis__header p, .hourly-mis__branch { margin: 5px 0; font-size: 14px; }
.hourly-mis__branch { font-weight: 700; }
.hourly-mis__table { width: 100%; table-layout: fixed; border-collapse: collapse; background: #fff; }
.hourly-mis__table th, .hourly-mis__table td { padding: 5px 4px; border: 1px solid #9fb2c3; font-size: 12px; text-align: center; }
.hourly-mis__table thead th { background: #dce7f1; font-weight: 700; }
.hourly-mis__table th:first-child, .hourly-mis__table td:first-child { width: 110px; text-align: left; }
.hourly-mis__operator th { background: #e3e8ed; text-align: left; }
.hourly-mis__operator span { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hourly-mis__total th, .hourly-mis__total td { background: #dde8f1; font-weight: 700; }
.hourly-mis__empty { padding: 28px !important; color: #73808b; font-style: italic; text-align: center !important; }

View File

@@ -43,6 +43,17 @@
<artifactId>spring-webmvc</artifactId> <artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version> <version>${spring.version}</version>
</dependency> </dependency>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>${jasperreports.version}</version>
<exclusions>
<exclusion>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <dependency>
<groupId>jakarta.servlet</groupId> <groupId>jakarta.servlet</groupId>

View File

@@ -9,18 +9,28 @@ import jakarta.servlet.http.HttpSession;
import matrix.nimble.mis.model.Filters; import matrix.nimble.mis.model.Filters;
import matrix.nimble.mis.model.MISHandler; import matrix.nimble.mis.model.MISHandler;
import matrix.nimble.model.Session; import matrix.nimble.model.Session;
import matrix.nimble.utilities.GlobalClass; import matrix.nimble.utilities.GlobalClass;
import matrix.services.mis.HourlyMisService;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@Controller @Controller
@SessionAttributes({"Sessvals"}) @SessionAttributes({"Sessvals"})
public class MIS { public class MIS {
private final HourlyMisService hourlyMisService;
public MIS(HourlyMisService hourlyMisService) {
this.hourlyMisService = hourlyMisService;
}
@RequestMapping(value="datetimerange",method=RequestMethod.POST ) @RequestMapping(value="datetimerange",method=RequestMethod.POST )
public String DateRangeFilter(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals,HttpSession session) public String DateRangeFilter(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals,HttpSession session)
{ {
@@ -82,17 +92,67 @@ public class MIS {
return "mis/misreport"; return "mis/misreport";
} }
@RequestMapping(value="dtmis",method=RequestMethod.POST ) @RequestMapping(value="dtmis",method=RequestMethod.POST )
public String DateRangeMIS(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals,@ModelAttribute(value="filter") Filters filter,HttpSession session) public String DateRangeMIS(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals,@ModelAttribute(value="filter") Filters filter,HttpSession session)
{ {
MISHandler MH=new MISHandler(); if (filter.getQid() == HourlyMisService.QUERY_ID) {
filter.setHtml(hourlyMisService.renderHtml(filter, Sessvals));
model.addAttribute("hourlyJasperReport", true);
model.addAttribute("filter", filter);
model.addAttribute("Sessvals", Sessvals);
return "mis/misreport";
}
MISHandler MH=new MISHandler();
MH.setProcessFlag(true); MH.setProcessFlag(true);
MH.setErrCode("5101"); MH.setErrCode("5101");
String [] Qvals=(filter.getFromdate()+GlobalClass.ColDelim+filter.getTodate()+GlobalClass.ColDelim+Sessvals.getBranchID()+GlobalClass.ColDelim+filter.getTitle()+GlobalClass.ColDelim+Sessvals.getBranchName()+GlobalClass.ColDelim+Sessvals.getCompanyName().toUpperCase()+GlobalClass.ColDelim+filter.getMtype()+GlobalClass.ColDelim).split(GlobalClass.ColDelim); String [] Qvals=(filter.getFromdate()+GlobalClass.ColDelim+filter.getTodate()+GlobalClass.ColDelim+Sessvals.getBranchID()+GlobalClass.ColDelim+filter.getTitle()+GlobalClass.ColDelim+Sessvals.getBranchName()+GlobalClass.ColDelim+Sessvals.getCompanyName().toUpperCase()+GlobalClass.ColDelim+filter.getMtype()+GlobalClass.ColDelim).split(GlobalClass.ColDelim);
MH.SimpleMIS(filter,filter.getQid(), Qvals); MH.SimpleMIS(filter,filter.getQid(), Qvals);
model.addAttribute("filter",filter); model.addAttribute("filter",filter);
model.addAttribute("Sessvals",Sessvals); model.addAttribute("Sessvals",Sessvals);
return "mis/misreport"; return "mis/misreport";
} }
@RequestMapping(value="dtmis/xlsx",method=RequestMethod.POST )
@ResponseBody
public ResponseEntity<byte[]> DateRangeMISXlsx(
@ModelAttribute(value="Sessvals") Session Sessvals,
@ModelAttribute(value="filter") Filters filter) {
if (filter.getQid() != HourlyMisService.QUERY_ID) {
return ResponseEntity.badRequest().build();
}
byte[] report = hourlyMisService.renderXlsx(filter, Sessvals);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=hourly-mis.xlsx")
.contentType(MediaType.parseMediaType(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
.body(report);
}
@RequestMapping(value="dtmis/pdf",method=RequestMethod.POST )
@ResponseBody
public ResponseEntity<byte[]> DateRangeMISPdf(
@ModelAttribute(value="Sessvals") Session Sessvals,
@ModelAttribute(value="filter") Filters filter) {
if (filter.getQid() != HourlyMisService.QUERY_ID) return ResponseEntity.badRequest().build();
return download(hourlyMisService.renderPdf(filter, Sessvals), "hourly-mis.pdf",
MediaType.APPLICATION_PDF);
}
@RequestMapping(value="dtmis/csv",method=RequestMethod.POST )
@ResponseBody
public ResponseEntity<byte[]> DateRangeMISCsv(
@ModelAttribute(value="Sessvals") Session Sessvals,
@ModelAttribute(value="filter") Filters filter) {
if (filter.getQid() != HourlyMisService.QUERY_ID) return ResponseEntity.badRequest().build();
return download(hourlyMisService.renderCsv(filter, Sessvals), "hourly-mis.csv",
MediaType.parseMediaType("text/csv"));
}
private ResponseEntity<byte[]> download(byte[] content, String filename, MediaType mediaType) {
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename)
.contentType(mediaType)
.body(content);
}
@RequestMapping(value="dtusermis",method=RequestMethod.POST ) @RequestMapping(value="dtusermis",method=RequestMethod.POST )
public String DateRangeUserMIS(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals,@ModelAttribute(value="filter") Filters filter,HttpSession session) public String DateRangeUserMIS(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals,@ModelAttribute(value="filter") Filters filter,HttpSession session)
{ {

View File

@@ -499,13 +499,13 @@ public class MISHandler {
CtrlMTimeRange+="<div class=\"widget\">"; CtrlMTimeRange+="<div class=\"widget\">";
CtrlMTimeRange+="<div class=\"lblcontainer\" style=\"width:85px\"><font color=\"red\">*</font> From Date</div>"; CtrlMTimeRange+="<div class=\"lblcontainer\" style=\"width:85px\"><font color=\"red\">*</font> From Date</div>";
CtrlMTimeRange+="<div class=\"inputcontainer\">"; CtrlMTimeRange+="<div class=\"inputcontainer\">";
CtrlMTimeRange+="<input type=\"text\" onblur=\"validate(this,'t','DateTime')\" onkeydown=\"return addSlashes(this,event)\" maxlength=\"19\" id=\"Fromdate\" name=\"Fromdate\" value=\""+frmdate+" 00:00:00\" />"; CtrlMTimeRange+=dateInput("Fromdate", frmdate + " 00:00:00", "datetime", "DateTime", 19);
CtrlMTimeRange+="</div>"; CtrlMTimeRange+="</div>";
CtrlMTimeRange+="</div>"; CtrlMTimeRange+="</div>";
CtrlMTimeRange+="<div class=\"widget\">"; CtrlMTimeRange+="<div class=\"widget\">";
CtrlMTimeRange+="<div class=\"lblcontainer\" style=\"width:85px\"><font color=\"red\">*</font> To Date</div>"; CtrlMTimeRange+="<div class=\"lblcontainer\" style=\"width:85px\"><font color=\"red\">*</font> To Date</div>";
CtrlMTimeRange+="<div class=\"inputcontainer\">"; CtrlMTimeRange+="<div class=\"inputcontainer\">";
CtrlMTimeRange+="<input type=\"text\" onblur=\"validate(this,'t','DateTime')\" onkeydown=\"return addSlashes(this,event)\" maxlength=\"19\" id=\"Todate\" name=\"Todate\" value=\""+todate+" 23:59:59\" />"; CtrlMTimeRange+=dateInput("Todate", todate + " 23:59:59", "datetime", "DateTime", 19);
CtrlMTimeRange+="</div>"; CtrlMTimeRange+="</div>";
CtrlMTimeRange+="</div>"; CtrlMTimeRange+="</div>";
return CtrlMTimeRange; return CtrlMTimeRange;
@@ -517,13 +517,13 @@ public class MISHandler {
CtrlDateTimeRange+="<div class=\"widget\">"; CtrlDateTimeRange+="<div class=\"widget\">";
CtrlDateTimeRange+="<div class=\"lblcontainer\" style=\"width:85px\"><font color=\"red\">*</font> From Date</div>"; CtrlDateTimeRange+="<div class=\"lblcontainer\" style=\"width:85px\"><font color=\"red\">*</font> From Date</div>";
CtrlDateTimeRange+="<div class=\"inputcontainer\">"; CtrlDateTimeRange+="<div class=\"inputcontainer\">";
CtrlDateTimeRange+="<input type=\"text\" onblur=\"validate(this,'t','DateTime')\" onkeydown=\"return addSlashes(this,event)\" maxlength=\"19\" id=\"Fromdate\" name=\"Fromdate\" value=\""+(frmdate+" 00:00:00")+"\" />"; CtrlDateTimeRange+=dateInput("Fromdate", frmdate + " 00:00:00", "datetime", "DateTime", 19);
CtrlDateTimeRange+="</div>"; CtrlDateTimeRange+="</div>";
CtrlDateTimeRange+="</div>"; CtrlDateTimeRange+="</div>";
CtrlDateTimeRange+="<div class=\"widget\">"; CtrlDateTimeRange+="<div class=\"widget\">";
CtrlDateTimeRange+="<div class=\"lblcontainer\" style=\"width:85px\"><font color=\"red\">*</font> To Date</div>"; CtrlDateTimeRange+="<div class=\"lblcontainer\" style=\"width:85px\"><font color=\"red\">*</font> To Date</div>";
CtrlDateTimeRange+="<div class=\"inputcontainer\">"; CtrlDateTimeRange+="<div class=\"inputcontainer\">";
CtrlDateTimeRange+="<input type=\"text\" onblur=\"validate(this,'t','DateTime')\" onkeydown=\"return addSlashes(this,event)\" maxlength=\"19\" id=\"Todate\" name=\"Todate\" value=\""+(frmdate+" 23:59:59")+"\" />"; CtrlDateTimeRange+=dateInput("Todate", frmdate + " 23:59:59", "datetime", "DateTime", 19);
CtrlDateTimeRange+="</div>"; CtrlDateTimeRange+="</div>";
CtrlDateTimeRange+="</div>"; CtrlDateTimeRange+="</div>";
return CtrlDateTimeRange; return CtrlDateTimeRange;
@@ -535,17 +535,26 @@ public class MISHandler {
CtrlDateTimeRange+="<div class=\"widget\">"; CtrlDateTimeRange+="<div class=\"widget\">";
CtrlDateTimeRange+="<div class=\"lblcontainer\" style=\"width:85px\"><font color=\"red\">*</font> From Date</div>"; CtrlDateTimeRange+="<div class=\"lblcontainer\" style=\"width:85px\"><font color=\"red\">*</font> From Date</div>";
CtrlDateTimeRange+="<div class=\"inputcontainer\">"; CtrlDateTimeRange+="<div class=\"inputcontainer\">";
CtrlDateTimeRange+="<input type=\"text\" onblur=\"validate(this,'t','Date')\" onkeydown=\"return addSlashes(this,event)\" maxlength=\"19\" id=\"Fromdate\" name=\"Fromdate\" value=\""+(frmdate)+"\" />"; CtrlDateTimeRange+=dateInput("Fromdate", frmdate, "date", "Date", 10);
CtrlDateTimeRange+="</div>"; CtrlDateTimeRange+="</div>";
CtrlDateTimeRange+="</div>"; CtrlDateTimeRange+="</div>";
CtrlDateTimeRange+="<div class=\"widget\">"; CtrlDateTimeRange+="<div class=\"widget\">";
CtrlDateTimeRange+="<div class=\"lblcontainer\" style=\"width:85px\"><font color=\"red\">*</font> To Date</div>"; CtrlDateTimeRange+="<div class=\"lblcontainer\" style=\"width:85px\"><font color=\"red\">*</font> To Date</div>";
CtrlDateTimeRange+="<div class=\"inputcontainer\">"; CtrlDateTimeRange+="<div class=\"inputcontainer\">";
CtrlDateTimeRange+="<input type=\"text\" onblur=\"validate(this,'t','Date')\" onkeydown=\"return addSlashes(this,event)\" maxlength=\"19\" id=\"Todate\" name=\"Todate\" value=\""+(frmdate)+"\" />"; CtrlDateTimeRange+=dateInput("Todate", frmdate, "date", "Date", 10);
CtrlDateTimeRange+="</div>"; CtrlDateTimeRange+="</div>";
CtrlDateTimeRange+="</div>"; CtrlDateTimeRange+="</div>";
return CtrlDateTimeRange; return CtrlDateTimeRange;
} }
private String dateInput(String id, String value, String mode, String validator, int maxlength)
{
return "<input type=\"text\" class=\"matrix-date-input\" data-date-mode=\"" + mode
+ "\" autocomplete=\"off\" inputmode=\"numeric\" placeholder=\""
+ ("datetime".equals(mode) ? "DD/MM/YYYY HH:MM:SS" : "DD/MM/YYYY")
+ "\" onblur=\"validate(this,'t','" + validator
+ "')\" onkeydown=\"return addSlashes(this,event)\" maxlength=\"" + maxlength
+ "\" id=\"" + id + "\" name=\"" + id + "\" value=\"" + value + "\" />";
}
private String FromDateToTimeControl() private String FromDateToTimeControl()
{ {
String frmdate=GlobalClass.DateTime("dd/MM/yyyy", new java.util.Date()); String frmdate=GlobalClass.DateTime("dd/MM/yyyy", new java.util.Date());

View File

@@ -0,0 +1,405 @@
package matrix.services.mis;
import lib.models.HourlyMisRecord;
import lib.models.ReportColumnDefinition;
import lib.models.ReportDefinition;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRPrintElement;
import net.sf.jasperreports.engine.JRPrintPage;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput;
import net.sf.jasperreports.export.SimpleWriterExporterOutput;
import net.sf.jasperreports.export.SimpleXlsxReportConfiguration;
import org.springframework.stereotype.Component;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@Component
public final class HourlyMisReportRenderer {
private static final int DATE_COLUMN_WIDTH = 105;
private static final int HOUR_COLUMN_WIDTH = 55;
private static final int REPORT_CONTENT_WIDTH = 1510;
private static final int FULL_CONTENT_WIDTH = 1690;
private final JasperReport report;
public HourlyMisReportRenderer() {
try (InputStream template = getClass().getResourceAsStream("/reports/hourly-mis.jrxml")) {
if (template == null) throw new IllegalStateException("Hourly MIS template is missing");
report = JasperCompileManager.compileReport(template);
} catch (Exception exception) {
throw new IllegalStateException("Unable to compile Hourly MIS template", exception);
}
}
public String html(List<HourlyMisRecord> rows, Map<String, Object> parameters,
ReportDefinition definition) {
int firstHour = definition.hideLeadingZeroColumns() ? firstActiveHour(rows) : 0;
Map<String, ReportColumnDefinition> columns = definition.columns().stream()
.filter(ReportColumnDefinition::visible)
.collect(java.util.stream.Collectors.toMap(
ReportColumnDefinition::columnKey, column -> column));
int visibleColumns = 1 + (columns.containsKey("total") ? 1 : 0);
for (int hour = firstHour; hour < 24; hour++) {
if (columns.containsKey("hour" + hour)) visibleColumns++;
}
StringBuilder html = new StringBuilder(4096);
html.append("<section class=\"hourly-mis\"><header class=\"hourly-mis__header\"><h1>")
.append(escape(parameters.get("COMPANY_NAME"))).append("</h1><h2>")
.append(escape(definition.title())).append("</h2><p>From: ")
.append(escape(parameters.get("FROM_DATE"))).append(" &nbsp; To: ")
.append(escape(parameters.get("TO_DATE"))).append("</p></header><div class=\"hourly-mis__branch\">Branch: ")
.append(escape(parameters.get("BRANCH_NAME"))).append("</div>")
.append("<table class=\"hourly-mis__table\"><thead><tr><th>")
.append(escape(label(columns, "date", "Date"))).append("</th>");
for (int hour = firstHour; hour < 24; hour++) {
if (columns.containsKey("hour" + hour)) html.append("<th>")
.append(escape(label(columns, "hour" + hour, String.valueOf(hour)))).append("</th>");
}
if (columns.containsKey("total")) html.append("<th>")
.append(escape(label(columns, "total", "Total"))).append("</th>");
html.append("</tr></thead><tbody>");
if (rows.isEmpty()) {
return html.append("<tr><td class=\"hourly-mis__empty\" colspan=\"")
.append(visibleColumns)
.append("\">No Records Found</td></tr></tbody></table></section>")
.toString();
}
String currentUser = null;
int[] totals = new int[24];
int grandTotal = 0;
for (HourlyMisRecord row : rows) {
if (!row.getDisplayName().equals(currentUser)) {
if (currentUser != null) {
appendTotalRow(html, totals, grandTotal, firstHour, columns);
totals = new int[24];
grandTotal = 0;
}
currentUser = row.getDisplayName();
html.append("<tr class=\"hourly-mis__operator\"><th colspan=\"")
.append(visibleColumns).append("\" title=\"")
.append(escape(currentUser)).append("\"><span>")
.append(escape(currentUser)).append("</span></th></tr>");
}
html.append("<tr><td>").append(row.getReceivedDate()).append("</td>");
for (int hour = firstHour; hour < 24; hour++) {
if (!columns.containsKey("hour" + hour)) continue;
int value = row.getHour(hour);
totals[hour] += value;
html.append("<td>").append(value).append("</td>");
}
grandTotal += row.getTotal();
if (columns.containsKey("total")) html.append("<td>").append(row.getTotal()).append("</td>");
html.append("</tr>");
}
appendTotalRow(html, totals, grandTotal, firstHour, columns);
return html.append("</tbody></table></section>").toString();
}
private String label(Map<String, ReportColumnDefinition> columns, String key, String fallback) {
ReportColumnDefinition column = columns.get(key);
return column == null || column.label() == null || column.label().isBlank()
? fallback : column.label();
}
private void appendTotalRow(StringBuilder html, int[] totals, int grandTotal, int firstHour,
Map<String, ReportColumnDefinition> columns) {
html.append("<tr class=\"hourly-mis__total\"><th>Total</th>");
for (int hour = firstHour; hour < 24; hour++) {
if (columns.containsKey("hour" + hour)) html.append("<td>").append(totals[hour]).append("</td>");
}
if (columns.containsKey("total")) html.append("<td>").append(grandTotal).append("</td>");
html.append("</tr>");
}
private String escape(Object value) {
return String.valueOf(value == null ? "" : value).replace("&", "&amp;")
.replace("<", "&lt;").replace(">", "&gt;").replace("\"", "&quot;")
.replace("'", "&#39;");
}
public byte[] xlsx(List<HourlyMisRecord> rows, Map<String, Object> parameters) {
int firstHour = firstActiveHour(rows);
int columnCount = 26 - firstHour;
try (Workbook workbook = new XSSFWorkbook();
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
var sheet = workbook.createSheet("hourly_mis");
CellStyle title = excelStyle(workbook, true, 14, null);
CellStyle subtitle = excelStyle(workbook, true, 11, null);
CellStyle text = excelStyle(workbook, false, 10, null);
CellStyle header = excelStyle(workbook, true, 10, "DCE7F1");
CellStyle group = excelStyle(workbook, true, 10, "E3E8ED");
CellStyle total = excelStyle(workbook, true, 10, "DDE8F1");
mergedCell(sheet, 0, 0, columnCount - 1, parameters.get("COMPANY_NAME"), title);
mergedCell(sheet, 1, 0, columnCount - 1, parameters.get("REPORT_TITLE"), subtitle);
mergedCell(sheet, 2, 0, columnCount - 1,
"From: " + parameters.get("FROM_DATE") + " To: " + parameters.get("TO_DATE"), text);
mergedCell(sheet, 4, 0, columnCount - 1, "Branch: " + parameters.get("BRANCH_NAME"), text);
Row headings = sheet.createRow(5);
excelCell(headings, 0, "Date", header);
int column = 1;
for (int hour = firstHour; hour < 24; hour++) excelCell(headings, column++, hour, header);
excelCell(headings, column, "Total", header);
writeExcelRows(sheet, rows, firstHour, group, text, total);
sheet.setColumnWidth(0, 16 * 256);
for (int index = 1; index < columnCount; index++) sheet.setColumnWidth(index, 9 * 256);
sheet.createFreezePane(1, 6);
workbook.write(output);
return output.toByteArray();
} catch (Exception exception) {
throw new IllegalStateException("Unable to export Hourly MIS", exception);
}
}
public byte[] pdf(List<HourlyMisRecord> rows, Map<String, Object> parameters) {
int firstHour = firstActiveHour(rows);
int columnCount = 26 - firstHour;
try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
Document document = new Document(PageSize.A3.rotate(), 28, 28, 24, 24);
PdfWriter.getInstance(document, output);
document.open();
document.add(centered(parameters.get("COMPANY_NAME"), 15, true));
document.add(centered(parameters.get("REPORT_TITLE"), 11, true));
document.add(centered("From: " + parameters.get("FROM_DATE") + " To: "
+ parameters.get("TO_DATE"), 9, false));
document.add(new Paragraph("Branch: " + parameters.get("BRANCH_NAME"), pdfFont(9, true)));
document.add(new Paragraph(" ", pdfFont(4, false)));
PdfPTable table = new PdfPTable(columnCount);
table.setWidthPercentage(100);
float[] widths = new float[columnCount];
widths[0] = 1.7f;
java.util.Arrays.fill(widths, 1, columnCount - 1, 1f);
widths[columnCount - 1] = 1.2f;
table.setWidths(widths);
pdfCell(table, "Date", true, "DCE7F1", 1);
for (int hour = firstHour; hour < 24; hour++) pdfCell(table, String.valueOf(hour), true, "DCE7F1", 1);
pdfCell(table, "Total", true, "DCE7F1", 1);
writePdfRows(table, rows, firstHour, columnCount);
document.add(table);
document.close();
return output.toByteArray();
} catch (Exception exception) {
throw new IllegalStateException("Unable to export Hourly MIS as PDF", exception);
}
}
private void writeExcelRows(org.apache.poi.ss.usermodel.Sheet sheet, List<HourlyMisRecord> records,
int firstHour, CellStyle groupStyle, CellStyle rowStyle, CellStyle totalStyle) {
int rowIndex = 6;
String user = null;
int[] totals = new int[24];
int grandTotal = 0;
for (HourlyMisRecord record : records) {
if (!record.getDisplayName().equals(user)) {
if (user != null) rowIndex = excelTotal(sheet, rowIndex, totals, grandTotal, firstHour, totalStyle);
user = record.getDisplayName();
totals = new int[24];
grandTotal = 0;
mergedCell(sheet, rowIndex++, 0, 25 - firstHour, user, groupStyle);
}
Row row = sheet.createRow(rowIndex++);
excelCell(row, 0, record.getReceivedDate().toString(), rowStyle);
int column = 1;
for (int hour = firstHour; hour < 24; hour++) {
int value = record.getHour(hour);
totals[hour] += value;
excelCell(row, column++, value, rowStyle);
}
grandTotal += record.getTotal();
excelCell(row, column, record.getTotal(), rowStyle);
}
if (user != null) excelTotal(sheet, rowIndex, totals, grandTotal, firstHour, totalStyle);
}
private int excelTotal(org.apache.poi.ss.usermodel.Sheet sheet, int rowIndex, int[] totals,
int grandTotal, int firstHour, CellStyle style) {
Row row = sheet.createRow(rowIndex++);
excelCell(row, 0, "Total", style);
int column = 1;
for (int hour = firstHour; hour < 24; hour++) excelCell(row, column++, totals[hour], style);
excelCell(row, column, grandTotal, style);
return rowIndex;
}
private CellStyle excelStyle(Workbook workbook, boolean bold, int fontSize, String color) {
CellStyle style = workbook.createCellStyle();
var font = workbook.createFont();
font.setBold(bold);
font.setFontHeightInPoints((short) fontSize);
style.setFont(font);
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setBorderTop(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
if (color != null) {
style.setFillForegroundColor(org.apache.poi.ss.usermodel.IndexedColors.valueOf(
color.equals("DCE7F1") ? "LIGHT_CORNFLOWER_BLUE" : "PALE_BLUE").getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
}
return style;
}
private void mergedCell(org.apache.poi.ss.usermodel.Sheet sheet, int rowIndex, int firstColumn,
int lastColumn, Object value, CellStyle style) {
Row row = sheet.createRow(rowIndex);
excelCell(row, firstColumn, value, style);
if (lastColumn > firstColumn) sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, firstColumn, lastColumn));
}
private void excelCell(Row row, int column, Object value, CellStyle style) {
Cell cell = row.createCell(column);
if (value instanceof Number number) cell.setCellValue(number.doubleValue());
else cell.setCellValue(String.valueOf(value == null ? "" : value));
cell.setCellStyle(style);
}
private void writePdfRows(PdfPTable table, List<HourlyMisRecord> records, int firstHour,
int columnCount) {
String user = null;
int[] totals = new int[24];
int grandTotal = 0;
for (HourlyMisRecord record : records) {
if (!record.getDisplayName().equals(user)) {
if (user != null) pdfTotal(table, totals, grandTotal, firstHour);
user = record.getDisplayName();
totals = new int[24];
grandTotal = 0;
pdfCell(table, user, true, "E3E8ED", columnCount);
}
pdfCell(table, record.getReceivedDate().toString(), false, null, 1);
for (int hour = firstHour; hour < 24; hour++) {
int value = record.getHour(hour);
totals[hour] += value;
pdfCell(table, String.valueOf(value), false, null, 1);
}
grandTotal += record.getTotal();
pdfCell(table, String.valueOf(record.getTotal()), false, null, 1);
}
if (user != null) pdfTotal(table, totals, grandTotal, firstHour);
}
private void pdfTotal(PdfPTable table, int[] totals, int grandTotal, int firstHour) {
pdfCell(table, "Total", true, "DDE8F1", 1);
for (int hour = firstHour; hour < 24; hour++) pdfCell(table, String.valueOf(totals[hour]), true, "DDE8F1", 1);
pdfCell(table, String.valueOf(grandTotal), true, "DDE8F1", 1);
}
private void pdfCell(PdfPTable table, String value, boolean bold, String background, int colspan) {
PdfPCell cell = new PdfPCell(new Phrase(value == null ? "" : value, pdfFont(8, bold)));
cell.setColspan(colspan);
cell.setHorizontalAlignment(colspan > 1 ? Element.ALIGN_LEFT : Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setPadding(5);
cell.setBorderColor(new BaseColor(159, 178, 195));
if (background != null) cell.setBackgroundColor(new BaseColor(
Integer.parseInt(background.substring(0, 2), 16),
Integer.parseInt(background.substring(2, 4), 16),
Integer.parseInt(background.substring(4, 6), 16)));
table.addCell(cell);
}
private Paragraph centered(Object value, int size, boolean bold) {
Paragraph paragraph = new Paragraph(String.valueOf(value == null ? "" : value), pdfFont(size, bold));
paragraph.setAlignment(Element.ALIGN_CENTER);
paragraph.setSpacingAfter(3);
return paragraph;
}
private Font pdfFont(int size, boolean bold) {
return FontFactory.getFont(FontFactory.HELVETICA, size,
bold ? Font.BOLD : Font.NORMAL, BaseColor.BLACK);
}
public byte[] csv(List<HourlyMisRecord> rows, Map<String, Object> parameters) {
try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
JRCsvExporter exporter = new JRCsvExporter();
exporter.setExporterInput(new SimpleExporterInput(fill(rows, parameters)));
exporter.setExporterOutput(new SimpleWriterExporterOutput(output));
exporter.exportReport();
return output.toByteArray();
} catch (Exception exception) {
throw new IllegalStateException("Unable to export Hourly MIS as CSV", exception);
}
}
private JasperPrint fill(List<HourlyMisRecord> rows, Map<String, Object> parameters)
throws JRException {
JasperPrint print = JasperFillManager.fillReport(report, new HashMap<>(parameters),
new JRBeanCollectionDataSource(rows, false));
compactLeadingEmptyHours(print, firstActiveHour(rows));
return print;
}
private int firstActiveHour(List<HourlyMisRecord> rows) {
if (rows.isEmpty()) return 0;
HourlyMisRecord first = rows.getFirst();
for (int hour = 0; hour < 24; hour++) {
if (first.getHour(hour) != 0) return hour;
}
return 0;
}
private void compactLeadingEmptyHours(JasperPrint print, int firstHour) {
int hiddenWidth = firstHour * HOUR_COLUMN_WIDTH;
int hiddenEnd = DATE_COLUMN_WIDTH + hiddenWidth;
int visibleTableWidth = REPORT_CONTENT_WIDTH - hiddenWidth;
double widthScale = (double) FULL_CONTENT_WIDTH / visibleTableWidth;
for (JRPrintPage page : print.getPages()) {
Iterator<JRPrintElement> elements = page.getElements().iterator();
while (elements.hasNext()) {
JRPrintElement element = elements.next();
if (element.getX() >= DATE_COLUMN_WIDTH && element.getX() < hiddenEnd) {
elements.remove();
} else if (element.getWidth() <= DATE_COLUMN_WIDTH
&& element.getX() < REPORT_CONTENT_WIDTH) {
int compactedX = element.getX() >= hiddenEnd
? element.getX() - hiddenWidth : element.getX();
element.setX((int) Math.round(compactedX * widthScale));
element.setWidth((int) Math.round(element.getWidth() * widthScale));
}
}
}
}
}

View File

@@ -0,0 +1,93 @@
package matrix.services.mis;
import com.cygnus.db.CygnusDbExecutor;
import com.cygnus.db.RowView;
import lib.models.HourlyMisRecord;
import matrix.nimble.mis.model.Filters;
import matrix.nimble.model.Session;
import org.springframework.stereotype.Service;
import java.sql.Date;
import java.time.LocalDate;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@Service
public class HourlyMisService {
public static final int QUERY_ID = 136;
private static final Set<String> SOURCES = Set.of("edp", "dedupe", "opr", "port", "bopr");
private final CygnusDbExecutor dbExecutor;
private final HourlyMisReportRenderer renderer;
private final ReportDefinitionService definitions;
public HourlyMisService(CygnusDbExecutor dbExecutor, HourlyMisReportRenderer renderer,
ReportDefinitionService definitions) {
this.dbExecutor = dbExecutor;
this.renderer = renderer;
this.definitions = definitions;
}
public String renderHtml(Filters filter, Session session) {
return renderer.html(records(filter, session), parameters(filter, session),
definitions.hourlyMis(filter.getTitle()));
}
public byte[] renderXlsx(Filters filter, Session session) {
return renderer.xlsx(records(filter, session), parameters(filter, session));
}
public byte[] renderPdf(Filters filter, Session session) {
return renderer.pdf(records(filter, session), parameters(filter, session));
}
public byte[] renderCsv(Filters filter, Session session) {
return renderer.csv(records(filter, session), parameters(filter, session));
}
private List<HourlyMisRecord> records(Filters filter, Session session) {
String source = source(filter.getMtype());
List<RowView> rows = dbExecutor.query(QUERY_ID, new Object[] {
source, filter.getFromdate(), filter.getTodate(), session.getCompanyID(),
session.getBranchID()
});
Map<String, HourlyMisRecord> records = new LinkedHashMap<>();
for (RowView row : rows) {
long userId = ((Number) row.get("user_id")).longValue();
LocalDate date = date(row.get("received_date"));
String name = String.valueOf(row.get("display_name"));
String key = userId + "|" + date;
HourlyMisRecord record = records.computeIfAbsent(key,
ignored -> new HourlyMisRecord(userId, name, date));
record.addCases(((Number) row.get("time_period")).intValue(),
((Number) row.get("case_count")).intValue());
}
return List.copyOf(records.values());
}
private Map<String, Object> parameters(Filters filter, Session session) {
return Map.of(
"REPORT_TITLE", filter.getTitle(),
"COMPANY_NAME", session.getCompanyName().toUpperCase(Locale.ROOT),
"BRANCH_NAME", session.getBranchName(),
"FROM_DATE", filter.getFromdate(),
"TO_DATE", filter.getTodate());
}
private String source(String value) {
String source = value == null ? "" : value.toLowerCase(Locale.ROOT);
if (!SOURCES.contains(source)) {
throw new IllegalArgumentException("Unsupported hourly MIS source");
}
return source;
}
private LocalDate date(Object value) {
if (value instanceof LocalDate localDate) return localDate;
if (value instanceof Date date) return date.toLocalDate();
return LocalDate.parse(String.valueOf(value));
}
}

View File

@@ -0,0 +1,55 @@
package matrix.services.mis;
import com.cygnus.db.CygnusDbExecutor;
import com.cygnus.db.RowView;
import lib.models.ReportColumnDefinition;
import lib.models.ReportDefinition;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class ReportDefinitionService {
private static final String DEFINITION_QUERY = "report-definition";
private final CygnusDbExecutor dbExecutor;
public ReportDefinitionService(CygnusDbExecutor dbExecutor) {
this.dbExecutor = dbExecutor;
}
public ReportDefinition hourlyMis(String fallbackTitle) {
try {
List<RowView> rows = dbExecutor.query(DEFINITION_QUERY, new Object[] { "hourly-mis" });
if (rows.isEmpty()) return defaults(fallbackTitle);
RowView first = rows.getFirst();
List<ReportColumnDefinition> columns = new ArrayList<>(rows.size());
for (RowView row : rows) {
columns.add(new ReportColumnDefinition(
text(row, "column_key"), text(row, "column_label"),
number(row, "display_order"), text(row, "alignment"),
number(row, "column_width"), bool(row, "is_visible"),
bool(row, "is_totalled")));
}
return new ReportDefinition("hourly-mis", text(first, "report_title"),
bool(first, "hide_leading_zero_columns"), List.copyOf(columns));
} catch (RuntimeException unavailable) {
return defaults(fallbackTitle);
}
}
private ReportDefinition defaults(String title) {
List<ReportColumnDefinition> columns = new ArrayList<>(26);
columns.add(new ReportColumnDefinition("date", "Date", 0, "left", 110, true, false));
for (int hour = 0; hour < 24; hour++) {
columns.add(new ReportColumnDefinition("hour" + hour, String.valueOf(hour),
hour + 1, "center", 55, true, true));
}
columns.add(new ReportColumnDefinition("total", "Total", 25, "center", 70, true, true));
return new ReportDefinition("hourly-mis", title, true, List.copyOf(columns));
}
private String text(RowView row, String column) { return String.valueOf(row.get(column)); }
private int number(RowView row, String column) { return ((Number) row.get(column)).intValue(); }
private boolean bool(RowView row, String column) { return Boolean.TRUE.equals(row.get(column)); }
}

View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="hourly_mis" pageWidth="1800" pageHeight="1200" orientation="Landscape" columnWidth="1690" leftMargin="55" rightMargin="55" topMargin="30" bottomMargin="30" whenNoDataType="NoDataSection">
<property name="net.sf.jasperreports.export.xlsx.freeze.row" value="5"/>
<parameter name="REPORT_TITLE" class="java.lang.String"/>
<parameter name="COMPANY_NAME" class="java.lang.String"/>
<parameter name="BRANCH_NAME" class="java.lang.String"/>
<parameter name="FROM_DATE" class="java.lang.String"/>
<parameter name="TO_DATE" class="java.lang.String"/>
<field name="displayName" class="java.lang.String"/>
<field name="receivedDate" class="java.time.LocalDate"/>
<field name="hour00" class="java.lang.Integer"/>
<field name="hour01" class="java.lang.Integer"/>
<field name="hour02" class="java.lang.Integer"/>
<field name="hour03" class="java.lang.Integer"/>
<field name="hour04" class="java.lang.Integer"/>
<field name="hour05" class="java.lang.Integer"/>
<field name="hour06" class="java.lang.Integer"/>
<field name="hour07" class="java.lang.Integer"/>
<field name="hour08" class="java.lang.Integer"/>
<field name="hour09" class="java.lang.Integer"/>
<field name="hour10" class="java.lang.Integer"/>
<field name="hour11" class="java.lang.Integer"/>
<field name="hour12" class="java.lang.Integer"/>
<field name="hour13" class="java.lang.Integer"/>
<field name="hour14" class="java.lang.Integer"/>
<field name="hour15" class="java.lang.Integer"/>
<field name="hour16" class="java.lang.Integer"/>
<field name="hour17" class="java.lang.Integer"/>
<field name="hour18" class="java.lang.Integer"/>
<field name="hour19" class="java.lang.Integer"/>
<field name="hour20" class="java.lang.Integer"/>
<field name="hour21" class="java.lang.Integer"/>
<field name="hour22" class="java.lang.Integer"/>
<field name="hour23" class="java.lang.Integer"/>
<field name="total" class="java.lang.Integer"/>
<variable name="sum_hour00" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour00}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour01" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour01}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour02" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour02}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour03" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour03}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour04" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour04}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour05" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour05}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour06" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour06}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour07" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour07}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour08" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour08}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour09" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour09}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour10" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour10}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour11" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour11}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour12" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour12}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour13" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour13}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour14" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour14}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour15" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour15}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour16" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour16}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour17" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour17}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour18" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour18}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour19" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour19}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour20" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour20}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour21" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour21}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour22" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour22}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_hour23" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{hour23}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<variable name="sum_total" class="java.lang.Integer" resetType="Group" resetGroup="operatorGroup" calculation="Sum"><variableExpression><![CDATA[$F{total}]]></variableExpression><initialValueExpression><![CDATA[0]]></initialValueExpression></variable>
<group name="operatorGroup">
<groupExpression><![CDATA[$F{displayName}]]></groupExpression>
<groupHeader><band height="25"><textField><reportElement x="0" y="2" width="1690" height="22" backcolor="#E3E8ED" mode="Opaque"/><textElement verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$F{displayName}]]></textFieldExpression></textField></band></groupHeader>
<groupFooter><band height="24"><staticText><reportElement x="0" y="0" width="105" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[Total]]></text></staticText>
<textField><reportElement x="105" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour00}]]></textFieldExpression></textField>
<textField><reportElement x="160" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour01}]]></textFieldExpression></textField>
<textField><reportElement x="215" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour02}]]></textFieldExpression></textField>
<textField><reportElement x="270" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour03}]]></textFieldExpression></textField>
<textField><reportElement x="325" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour04}]]></textFieldExpression></textField>
<textField><reportElement x="380" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour05}]]></textFieldExpression></textField>
<textField><reportElement x="435" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour06}]]></textFieldExpression></textField>
<textField><reportElement x="490" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour07}]]></textFieldExpression></textField>
<textField><reportElement x="545" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour08}]]></textFieldExpression></textField>
<textField><reportElement x="600" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour09}]]></textFieldExpression></textField>
<textField><reportElement x="655" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour10}]]></textFieldExpression></textField>
<textField><reportElement x="710" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour11}]]></textFieldExpression></textField>
<textField><reportElement x="765" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour12}]]></textFieldExpression></textField>
<textField><reportElement x="820" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour13}]]></textFieldExpression></textField>
<textField><reportElement x="875" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour14}]]></textFieldExpression></textField>
<textField><reportElement x="930" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour15}]]></textFieldExpression></textField>
<textField><reportElement x="985" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour16}]]></textFieldExpression></textField>
<textField><reportElement x="1040" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour17}]]></textFieldExpression></textField>
<textField><reportElement x="1095" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour18}]]></textFieldExpression></textField>
<textField><reportElement x="1150" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour19}]]></textFieldExpression></textField>
<textField><reportElement x="1205" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour20}]]></textFieldExpression></textField>
<textField><reportElement x="1260" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour21}]]></textFieldExpression></textField>
<textField><reportElement x="1315" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour22}]]></textFieldExpression></textField>
<textField><reportElement x="1370" y="0" width="55" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_hour23}]]></textFieldExpression></textField>
<textField><reportElement x="1425" y="0" width="85" height="22" backcolor="#DDE8F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><textFieldExpression><![CDATA[$V{sum_total}]]></textFieldExpression></textField></band></groupFooter>
</group>
<title><band height="82">
<textField><reportElement x="0" y="0" width="1690" height="24"/><textElement textAlignment="Center"><font size="16" isBold="true"/></textElement><textFieldExpression><![CDATA[$P{COMPANY_NAME}]]></textFieldExpression></textField>
<textField><reportElement x="0" y="25" width="1690" height="20"/><textElement textAlignment="Center"><font size="12" isBold="true"/></textElement><textFieldExpression><![CDATA[$P{REPORT_TITLE}]]></textFieldExpression></textField>
<textField><reportElement x="0" y="46" width="1690" height="18"/><textElement textAlignment="Center"><font size="11"/></textElement><textFieldExpression><![CDATA["From: " + $P{FROM_DATE} + " To: " + $P{TO_DATE}]]></textFieldExpression></textField>
<textField><reportElement x="0" y="64" width="1690" height="18"/><textElement><font size="11" isBold="true"/></textElement><textFieldExpression><![CDATA["Branch: " + $P{BRANCH_NAME}]]></textFieldExpression></textField>
</band></title>
<columnHeader><band height="24"><staticText><reportElement x="0" y="0" width="105" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[Date]]></text></staticText>
<staticText><reportElement x="105" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[0]]></text></staticText>
<staticText><reportElement x="160" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[1]]></text></staticText>
<staticText><reportElement x="215" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[2]]></text></staticText>
<staticText><reportElement x="270" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[3]]></text></staticText>
<staticText><reportElement x="325" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[4]]></text></staticText>
<staticText><reportElement x="380" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[5]]></text></staticText>
<staticText><reportElement x="435" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[6]]></text></staticText>
<staticText><reportElement x="490" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[7]]></text></staticText>
<staticText><reportElement x="545" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[8]]></text></staticText>
<staticText><reportElement x="600" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[9]]></text></staticText>
<staticText><reportElement x="655" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[10]]></text></staticText>
<staticText><reportElement x="710" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[11]]></text></staticText>
<staticText><reportElement x="765" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[12]]></text></staticText>
<staticText><reportElement x="820" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[13]]></text></staticText>
<staticText><reportElement x="875" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[14]]></text></staticText>
<staticText><reportElement x="930" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[15]]></text></staticText>
<staticText><reportElement x="985" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[16]]></text></staticText>
<staticText><reportElement x="1040" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[17]]></text></staticText>
<staticText><reportElement x="1095" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[18]]></text></staticText>
<staticText><reportElement x="1150" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[19]]></text></staticText>
<staticText><reportElement x="1205" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[20]]></text></staticText>
<staticText><reportElement x="1260" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[21]]></text></staticText>
<staticText><reportElement x="1315" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[22]]></text></staticText>
<staticText><reportElement x="1370" y="0" width="55" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[23]]></text></staticText>
<staticText><reportElement x="1425" y="0" width="85" height="24" backcolor="#DCE7F1" mode="Opaque"/><box><pen lineWidth="0.5" lineColor="#9FB2C3"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10" isBold="true"/></textElement><text><![CDATA[Total]]></text></staticText></band></columnHeader>
<detail><band height="22"><textField><reportElement x="0" y="0" width="105" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Left" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{receivedDate}]]></textFieldExpression></textField>
<textField><reportElement x="105" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour00}]]></textFieldExpression></textField>
<textField><reportElement x="160" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour01}]]></textFieldExpression></textField>
<textField><reportElement x="215" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour02}]]></textFieldExpression></textField>
<textField><reportElement x="270" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour03}]]></textFieldExpression></textField>
<textField><reportElement x="325" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour04}]]></textFieldExpression></textField>
<textField><reportElement x="380" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour05}]]></textFieldExpression></textField>
<textField><reportElement x="435" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour06}]]></textFieldExpression></textField>
<textField><reportElement x="490" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour07}]]></textFieldExpression></textField>
<textField><reportElement x="545" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour08}]]></textFieldExpression></textField>
<textField><reportElement x="600" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour09}]]></textFieldExpression></textField>
<textField><reportElement x="655" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour10}]]></textFieldExpression></textField>
<textField><reportElement x="710" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour11}]]></textFieldExpression></textField>
<textField><reportElement x="765" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour12}]]></textFieldExpression></textField>
<textField><reportElement x="820" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour13}]]></textFieldExpression></textField>
<textField><reportElement x="875" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour14}]]></textFieldExpression></textField>
<textField><reportElement x="930" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour15}]]></textFieldExpression></textField>
<textField><reportElement x="985" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour16}]]></textFieldExpression></textField>
<textField><reportElement x="1040" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour17}]]></textFieldExpression></textField>
<textField><reportElement x="1095" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour18}]]></textFieldExpression></textField>
<textField><reportElement x="1150" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour19}]]></textFieldExpression></textField>
<textField><reportElement x="1205" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour20}]]></textFieldExpression></textField>
<textField><reportElement x="1260" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour21}]]></textFieldExpression></textField>
<textField><reportElement x="1315" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour22}]]></textFieldExpression></textField>
<textField><reportElement x="1370" y="0" width="55" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{hour23}]]></textFieldExpression></textField>
<textField><reportElement x="1425" y="0" width="85" height="22"/><box><pen lineWidth="0.35" lineColor="#B9C8D5"/></box><textElement textAlignment="Center" verticalAlignment="Middle"><font size="10"/></textElement><textFieldExpression><![CDATA[$F{total}]]></textFieldExpression></textField></band></detail>
<noData><band height="80"><staticText><reportElement x="0" y="25" width="1690" height="30"/><textElement textAlignment="Center"><font size="13" isBold="true" isItalic="true"/></textElement><text><![CDATA[No Records Found]]></text></staticText></band></noData>
</jasperReport>

View File

@@ -9,6 +9,9 @@ public interface CygnusDbExecutor {
<T> List<T> query(int queryId, Object[] parameters, Class<T> responseType); <T> List<T> query(int queryId, Object[] parameters, Class<T> responseType);
<T> List<T> query(int queryId, Object[] parameters, RowMapper<T> mapper); <T> List<T> query(int queryId, Object[] parameters, RowMapper<T> mapper);
List<RowView> query(int queryId, Object[] parameters); List<RowView> query(int queryId, Object[] parameters);
default List<RowView> query(String queryKey, Object[] parameters) {
throw new UnsupportedOperationException("Query keys are not supported by this executor");
}
<T> Optional<T> queryOne(int queryId, Object[] parameters, Class<T> responseType); <T> Optional<T> queryOne(int queryId, Object[] parameters, Class<T> responseType);
int insert(int queryId, Object[] parameters); int insert(int queryId, Object[] parameters);
<K> K insert(int queryId, Object[] parameters, Class<K> generatedKeyType); <K> K insert(int queryId, Object[] parameters, Class<K> generatedKeyType);

View File

@@ -63,6 +63,15 @@ public final class JdbcCygnusDbExecutor implements CygnusDbExecutor {
return query(queryId, parameters, RowView.class); return query(queryId, parameters, RowView.class);
} }
@Override
public List<RowView> query(String queryKey, Object[] parameters) {
QueryDefinition definition = queryProvider.get(queryKey);
if (definition.type() != QueryType.SELECT) throw new QueryDefinitionException(
"Query " + queryKey + " is " + definition.type() + ", not " + QueryType.SELECT);
return withReadConnection(definition.queryId(), connection -> query(
connection, definition, parameters, RowView.class));
}
@Override @Override
public <T> Optional<T> queryOne(int queryId, Object[] parameters, Class<T> responseType) { public <T> Optional<T> queryOne(int queryId, Object[] parameters, Class<T> responseType) {
List<T> rows = query(queryId, parameters, responseType); List<T> rows = query(queryId, parameters, responseType);

View File

@@ -0,0 +1,6 @@
-- Structured Hourly MIS dataset used by JasperReports. The legacy hourlymis()
-- function is retained temporarily for rollback, but query 136 no longer calls it.
UPDATE platform.application_query
SET query_text = 'select!C0L!WITH args AS (SELECT ?::text AS source, ?::timestamp AS from_date, ?::timestamp AS to_date, ?::integer AS company_id, ?::integer AS branch_id), hourly_data AS (SELECT m.addedby::bigint AS user_id, COALESCE(NULLIF(m.addedbyuser, ''''), u.displayname) AS display_name, m.receivedate::date AS received_date, EXTRACT(HOUR FROM m.addedon)::integer AS time_period FROM main m CROSS JOIN args a LEFT JOIN app_user u ON u.user_id=m.addedby WHERE a.source=''edp'' AND m.company_id=a.company_id AND m.branch_id=a.branch_id AND m.addedon BETWEEN a.from_date AND a.to_date UNION ALL SELECT d.deduperunby::bigint, u.displayname, m.receivedate::date, EXTRACT(HOUR FROM d.deduperunon)::integer FROM main_mainopr m JOIN dedupe d ON d.uuid=m.uuid CROSS JOIN args a LEFT JOIN app_user u ON u.user_id=d.deduperunby WHERE a.source=''dedupe'' AND m.company_id=a.company_id AND m.branch_id=a.branch_id AND m.isdeleted=0 AND d.deduperunon BETWEEN a.from_date AND a.to_date UNION ALL SELECT r.opruser::bigint, u.displayname, r.oprtime::date, EXTRACT(HOUR FROM r.oprtime)::integer FROM main_mainopr m JOIN riskalerts r ON r.uuid=m.uuid CROSS JOIN args a LEFT JOIN app_user u ON u.user_id=r.opruser WHERE a.source=''opr'' AND m.company_id=a.company_id AND m.branch_id=a.branch_id AND r.oprtime BETWEEN a.from_date AND a.to_date UNION ALL SELECT p.portfolio_id::bigint, p.portname, m.sdoneon::date, EXTRACT(HOUR FROM m.sdoneon)::integer FROM main_mainopr m JOIN portfolio p ON p.portfolio_id=m.portfolio_id CROSS JOIN args a WHERE a.source=''port'' AND m.company_id=a.company_id AND m.branch_id=a.branch_id AND m.sdone=1 AND m.sdoneon BETWEEN a.from_date AND a.to_date UNION ALL SELECT CASE r.visit WHEN ''RESI'' THEN m.rbksoftupdtdby WHEN ''OFFICE'' THEN m.obksoftupdtdby ELSE m.pbksoftupdtdby END::bigint, u.displayname, CASE r.visit WHEN ''RESI'' THEN m.rbksoftupdtdon WHEN ''OFFICE'' THEN m.obksoftupdtdon ELSE m.pbksoftupdtdon END::date, EXTRACT(HOUR FROM CASE r.visit WHEN ''RESI'' THEN m.rbksoftupdtdon WHEN ''OFFICE'' THEN m.obksoftupdtdon ELSE m.pbksoftupdtdon END)::integer FROM main_mainopr m JOIN riskalerts r ON r.uuid=m.uuid CROSS JOIN args a LEFT JOIN app_user u ON u.user_id=CASE r.visit WHEN ''RESI'' THEN m.rbksoftupdtdby WHEN ''OFFICE'' THEN m.obksoftupdtdby ELSE m.pbksoftupdtdby END WHERE a.source=''bopr'' AND m.company_id=a.company_id AND m.branch_id=a.branch_id AND CASE r.visit WHEN ''RESI'' THEN m.rbksoftupdtdon WHEN ''OFFICE'' THEN m.obksoftupdtdon ELSE m.pbksoftupdtdon END BETWEEN a.from_date AND a.to_date) SELECT user_id, COALESCE(display_name, ''Unknown'') AS display_name, received_date, time_period, COUNT(*)::integer AS case_count FROM hourly_data GROUP BY user_id, display_name, received_date, time_period ORDER BY display_name, received_date, time_period',
ismigrated = true
WHERE query_id = 136;

View File

@@ -0,0 +1,44 @@
CREATE TABLE IF NOT EXISTS platform.report_definition (
report_key varchar(100) PRIMARY KEY,
report_title varchar(200) NOT NULL,
hide_leading_zero_columns boolean NOT NULL DEFAULT false,
enabled boolean NOT NULL DEFAULT true,
updated_at timestamptz NOT NULL DEFAULT current_timestamp
);
CREATE TABLE IF NOT EXISTS platform.report_column_definition (
report_key varchar(100) NOT NULL REFERENCES platform.report_definition(report_key) ON DELETE CASCADE,
column_key varchar(100) NOT NULL,
column_label varchar(100) NOT NULL,
display_order integer NOT NULL,
alignment varchar(10) NOT NULL DEFAULT 'left',
column_width integer NOT NULL DEFAULT 80,
is_visible boolean NOT NULL DEFAULT true,
is_totalled boolean NOT NULL DEFAULT false,
PRIMARY KEY (report_key, column_key)
);
INSERT INTO platform.report_definition(report_key, report_title, hide_leading_zero_columns)
VALUES ('hourly-mis', 'HOURLY MIS (EDP)', true)
ON CONFLICT (report_key) DO NOTHING;
INSERT INTO platform.report_column_definition
(report_key,column_key,column_label,display_order,alignment,column_width,is_visible,is_totalled)
VALUES ('hourly-mis','date','Date',0,'left',110,true,false),
('hourly-mis','total','Total',25,'center',70,true,true)
ON CONFLICT (report_key,column_key) DO NOTHING;
INSERT INTO platform.report_column_definition
(report_key,column_key,column_label,display_order,alignment,column_width,is_visible,is_totalled)
SELECT 'hourly-mis', 'hour'||hour, hour::text, hour+1, 'center', 55, true, true
FROM generate_series(0,23) hour
ON CONFLICT (report_key,column_key) DO NOTHING;
UPDATE platform.application_query
SET query_text='select!C0L!SELECT r.report_title,r.hide_leading_zero_columns,c.column_key,c.column_label,c.display_order,c.alignment,c.column_width,c.is_visible,c.is_totalled FROM platform.report_definition r JOIN platform.report_column_definition c ON c.report_key=r.report_key WHERE r.report_key=? AND r.enabled=true ORDER BY c.display_order',
enabled=true, updated_at=current_timestamp
WHERE query_key='report-definition';
INSERT INTO platform.application_query(query_key, query_text, enabled)
SELECT 'report-definition', 'select!C0L!SELECT r.report_title,r.hide_leading_zero_columns,c.column_key,c.column_label,c.display_order,c.alignment,c.column_width,c.is_visible,c.is_totalled FROM platform.report_definition r JOIN platform.report_column_definition c ON c.report_key=r.report_key WHERE r.report_key=? AND r.enabled=true ORDER BY c.display_order', true
WHERE NOT EXISTS (SELECT 1 FROM platform.application_query WHERE query_key='report-definition');

View File

@@ -136,7 +136,7 @@ Query132!C0L!select!C0L!select d.uuid,d.mvcode,d.applno,d.customername,d.apptype
Query133!C0L!select!C0L!select uuid,product,maincompany,bkbranchname,to_char(receivedate,'DD/MM/YYYY') as receivedate,applno,upper(customername) cname,bank_branch_id,'DDUP Report' as label1,name as portname,to_char(receivedate,'dd/MM/yyyy') as receivedate,applno,customername,'' as blankcol1,'' as blank1,(case when earlier='Y' then earremarks else 'NO EARLIER MATCH FOUND' end) as earremarks,'' as blank2,(case when negative='Y' then negremarks else 'NO NEGATIVE MATCH FOUND' end) as negremarks,(case when negative='Y' then 'STATUS: NEGATIVE' else '' end) as label3,'' as blankcol2,'End of Report' as label4,to_char(deduperunon,'HH24:MI:SS') as dedtime,'Supervisor Name' as label5,'Agency Seal' as label6,'QR Code' as label7,portsupervisor,'images/signs/'||supervisor||'.png' as seal,mvcode||'-'||applno||'-'||customername||'-EAR-'||earlier||'-NEG-'||negative as bcode from banklist_main_dedupe d where portfolio_id not in (select portfolio_id from denied_process where process_id=13 and isdenied=1) and (val0) val1 Query133!C0L!select!C0L!select uuid,product,maincompany,bkbranchname,to_char(receivedate,'DD/MM/YYYY') as receivedate,applno,upper(customername) cname,bank_branch_id,'DDUP Report' as label1,name as portname,to_char(receivedate,'dd/MM/yyyy') as receivedate,applno,customername,'' as blankcol1,'' as blank1,(case when earlier='Y' then earremarks else 'NO EARLIER MATCH FOUND' end) as earremarks,'' as blank2,(case when negative='Y' then negremarks else 'NO NEGATIVE MATCH FOUND' end) as negremarks,(case when negative='Y' then 'STATUS: NEGATIVE' else '' end) as label3,'' as blankcol2,'End of Report' as label4,to_char(deduperunon,'HH24:MI:SS') as dedtime,'Supervisor Name' as label5,'Agency Seal' as label6,'QR Code' as label7,portsupervisor,'images/signs/'||supervisor||'.png' as seal,mvcode||'-'||applno||'-'||customername||'-EAR-'||earlier||'-NEG-'||negative as bcode from banklist_main_dedupe d where portfolio_id not in (select portfolio_id from denied_process where process_id=13 and isdenied=1) and (val0) val1
Query134!C0L!select!C0L!select portfolio_id,portname from portfolio where portfolio_id not in (select portfolio_id from denied_process where process_id=13 and isdenied=1) and branch_id=val0 Query134!C0L!select!C0L!select portfolio_id,portname from portfolio where portfolio_id not in (select portfolio_id from denied_process where process_id=13 and isdenied=1) and branch_id=val0
Query135!C0L!insert!C0L!insert into sys_event_log (msgtype,code,message,details,user_id,occuredon,ipaddr,branch_id) values ('val3','val2','val4','val5',val0,'val6','127.0.0.1',val1) Query135!C0L!insert!C0L!insert into sys_event_log (msgtype,code,message,details,user_id,occuredon,ipaddr,branch_id) values ('val3','val2','val4','val5',val0,'val6','127.0.0.1',val1)
Query136!C0L!procedure!C0L!select hourlymis('val0','val1',val2,'val3','val4','val5','val6') Query136!C0L!select!C0L!WITH args AS (SELECT ?::text AS source, ?::timestamp AS from_date, ?::timestamp AS to_date, ?::integer AS company_id, ?::integer AS branch_id), hourly_data AS (SELECT m.addedby::bigint AS user_id, COALESCE(NULLIF(m.addedbyuser, ''), u.displayname) AS display_name, m.receivedate::date AS received_date, EXTRACT(HOUR FROM m.addedon)::integer AS time_period FROM main m CROSS JOIN args a LEFT JOIN app_user u ON u.user_id=m.addedby WHERE a.source='edp' AND m.company_id=a.company_id AND m.branch_id=a.branch_id AND m.addedon BETWEEN a.from_date AND a.to_date UNION ALL SELECT d.deduperunby::bigint, u.displayname, m.receivedate::date, EXTRACT(HOUR FROM d.deduperunon)::integer FROM main_mainopr m JOIN dedupe d ON d.uuid=m.uuid CROSS JOIN args a LEFT JOIN app_user u ON u.user_id=d.deduperunby WHERE a.source='dedupe' AND m.company_id=a.company_id AND m.branch_id=a.branch_id AND m.isdeleted=0 AND d.deduperunon BETWEEN a.from_date AND a.to_date UNION ALL SELECT r.opruser::bigint, u.displayname, r.oprtime::date, EXTRACT(HOUR FROM r.oprtime)::integer FROM main_mainopr m JOIN riskalerts r ON r.uuid=m.uuid CROSS JOIN args a LEFT JOIN app_user u ON u.user_id=r.opruser WHERE a.source='opr' AND m.company_id=a.company_id AND m.branch_id=a.branch_id AND r.oprtime BETWEEN a.from_date AND a.to_date UNION ALL SELECT p.portfolio_id::bigint, p.portname, m.sdoneon::date, EXTRACT(HOUR FROM m.sdoneon)::integer FROM main_mainopr m JOIN portfolio p ON p.portfolio_id=m.portfolio_id CROSS JOIN args a WHERE a.source='port' AND m.company_id=a.company_id AND m.branch_id=a.branch_id AND m.sdone=1 AND m.sdoneon BETWEEN a.from_date AND a.to_date UNION ALL SELECT CASE r.visit WHEN 'RESI' THEN m.rbksoftupdtdby WHEN 'OFFICE' THEN m.obksoftupdtdby ELSE m.pbksoftupdtdby END::bigint, u.displayname, CASE r.visit WHEN 'RESI' THEN m.rbksoftupdtdon WHEN 'OFFICE' THEN m.obksoftupdtdon ELSE m.pbksoftupdtdon END::date, EXTRACT(HOUR FROM CASE r.visit WHEN 'RESI' THEN m.rbksoftupdtdon WHEN 'OFFICE' THEN m.obksoftupdtdon ELSE m.pbksoftupdtdon END)::integer FROM main_mainopr m JOIN riskalerts r ON r.uuid=m.uuid CROSS JOIN args a LEFT JOIN app_user u ON u.user_id=CASE r.visit WHEN 'RESI' THEN m.rbksoftupdtdby WHEN 'OFFICE' THEN m.obksoftupdtdby ELSE m.pbksoftupdtdby END WHERE a.source='bopr' AND m.company_id=a.company_id AND m.branch_id=a.branch_id AND CASE r.visit WHEN 'RESI' THEN m.rbksoftupdtdon WHEN 'OFFICE' THEN m.obksoftupdtdon ELSE m.pbksoftupdtdon END BETWEEN a.from_date AND a.to_date) SELECT user_id, COALESCE(display_name, 'Unknown') AS display_name, received_date, time_period, COUNT(*)::integer AS case_count FROM hourly_data GROUP BY user_id, display_name, received_date, time_period ORDER BY display_name, received_date, time_period
Query137!C0L!procedure!C0L!select receivedcases('val0', 'val1', val2, val3, val4, 'val5', 'val6', 'val7', 'val8') Query137!C0L!procedure!C0L!select receivedcases('val0', 'val1', val2, val3, val4, 'val5', 'val6', 'val7', 'val8')
Query138!C0L!procedure!C0L!select reportpending(val0, val1, val2, 'val3', 'val4', 'val5', 'val6') Query138!C0L!procedure!C0L!select reportpending(val0, val1, val2, 'val3', 'val4', 'val5', 'val6')
Query139!C0L!procedure!C0L!select pendingcases(val0, val1, val2, 'val3', 'val4', 'val5', 'val6') Query139!C0L!procedure!C0L!select pendingcases(val0, val1, val2, 'val3', 'val4', 'val5', 'val6')

View File

@@ -40,5 +40,6 @@
<reactor.netty.version>1.2.8</reactor.netty.version> <reactor.netty.version>1.2.8</reactor.netty.version>
<nimbus.version>10.4</nimbus.version> <nimbus.version>10.4</nimbus.version>
<lombok.version>1.18.46</lombok.version> <lombok.version>1.18.46</lombok.version>
<jasperreports.version>6.21.5</jasperreports.version>
</properties> </properties>
</project> </project>