Migrated Queries - 4,5 and 70

This commit is contained in:
2026-08-01 23:10:28 +05:30
parent 7e4fb66fc6
commit 452e6189e4
24 changed files with 372 additions and 146 deletions

View File

@@ -13,7 +13,7 @@ public class CasePunching {
private Map<String, String> optionsl; private Map<String, String> optionsl;
private Map<String, List<Option>> options; private Map<String, List<Option>> options;
private List<String> visibleSections; private List<String> visibleSections;
private Integer portfolioId; private Short portfolioId;
private Integer formMode; private Integer formMode;
private String userId; private String userId;
private String dynamicFields; private String dynamicFields;

View File

@@ -0,0 +1,29 @@
package lib.models;
import java.io.Serial;
import java.io.Serializable;
import lombok.Builder;
import lombok.Value;
/** Immutable, type-safe representation of an authenticated Cygnus user. */
@Value
@Builder
public class UserSession implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
Short companyId;
String companyName;
String companyCode;
Short branchId;
String branchName;
String branchCode;
String branchLocation;
Short userId;
String username;
String userDisplayName;
Short userGroupId;
String userGroupName;
String loginTime;
String menuHtml;
}

Binary file not shown.

View File

@@ -2,3 +2,4 @@
/Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/main/java/lib/models/CasePunching.java /Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/main/java/lib/models/CasePunching.java
/Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/main/java/lib/models/ErrorDetails.java /Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/main/java/lib/models/ErrorDetails.java
/Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/main/java/lib/models/Option.java /Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/main/java/lib/models/Option.java
/Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/main/java/lib/models/UserSession.java

View File

@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd" version="3.0.2" name="lib.models.ErrorDetailsTest" time="0.024" tests="2" errors="0" skipped="0" failures="0"> <testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd" version="3.0.2" name="lib.models.ErrorDetailsTest" time="0.028" tests="2" errors="0" skipped="0" failures="0">
<properties> <properties>
<property name="java.specification.version" value="25"/> <property name="java.specification.version" value="21"/>
<property name="sun.jnu.encoding" value="UTF-8"/> <property name="sun.jnu.encoding" value="UTF-8"/>
<property name="java.class.path" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/test-classes:/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/classes:/Users/maddy/.m2/repository/org/projectlombok/lombok/1.18.46/lombok-1.18.46.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter/5.12.2/junit-jupiter-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.12.2/junit-jupiter-api-5.12.2.jar:/Users/maddy/.m2/repository/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar:/Users/maddy/.m2/repository/org/junit/platform/junit-platform-commons/1.12.2/junit-platform-commons-1.12.2.jar:/Users/maddy/.m2/repository/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-params/5.12.2/junit-jupiter-params-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.12.2/junit-jupiter-engine-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/platform/junit-platform-engine/1.12.2/junit-platform-engine-1.12.2.jar:"/> <property name="java.class.path" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/test-classes:/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/classes:/Users/maddy/.m2/repository/org/projectlombok/lombok/1.18.46/lombok-1.18.46.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter/5.12.2/junit-jupiter-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.12.2/junit-jupiter-api-5.12.2.jar:/Users/maddy/.m2/repository/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar:/Users/maddy/.m2/repository/org/junit/platform/junit-platform-commons/1.12.2/junit-platform-commons-1.12.2.jar:/Users/maddy/.m2/repository/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-params/5.12.2/junit-jupiter-params-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.12.2/junit-jupiter-engine-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/platform/junit-platform-engine/1.12.2/junit-platform-engine-1.12.2.jar:"/>
<property name="java.vm.vendor" value="Homebrew"/> <property name="java.vm.vendor" value="Microsoft"/>
<property name="sun.arch.data.model" value="64"/> <property name="sun.arch.data.model" value="64"/>
<property name="java.vendor.url" value="https://github.com/Homebrew/homebrew-core/issues"/> <property name="java.vendor.url" value="https://www.microsoft.com"/>
<property name="os.name" value="Mac OS X"/> <property name="os.name" value="Mac OS X"/>
<property name="java.vm.specification.version" value="25"/> <property name="java.vm.specification.version" value="21"/>
<property name="sun.java.launcher" value="SUN_STANDARD"/> <property name="sun.java.launcher" value="SUN_STANDARD"/>
<property name="user.country" value="US"/> <property name="user.country" value="US"/>
<property name="sun.boot.library.path" value="/opt/homebrew/Cellar/openjdk/25.0.2/libexec/openjdk.jdk/Contents/Home/lib"/> <property name="sun.boot.library.path" value="/Users/maddy/Library/Java/JavaVirtualMachines/ms-21.0.8/Contents/Home/lib"/>
<property name="sun.java.command" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/surefire/surefirebooter-20260801204253825_3.jar /Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/surefire 2026-08-01T20-42-53_787-jvmRun1 surefire-20260801204253825_1tmp surefire_0-20260801204253825_2tmp"/> <property name="sun.java.command" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/surefire/surefirebooter-20260801225315947_3.jar /Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/surefire 2026-08-01T22-53-15_920-jvmRun1 surefire-20260801225315947_1tmp surefire_0-20260801225315947_2tmp"/>
<property name="http.nonProxyHosts" value="local|*.local|169.254/16|*.169.254/16"/> <property name="http.nonProxyHosts" value="local|*.local|169.254/16|*.169.254/16"/>
<property name="jdk.debug" value="release"/> <property name="jdk.debug" value="release"/>
<property name="surefire.test.class.path" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/test-classes:/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/classes:/Users/maddy/.m2/repository/org/projectlombok/lombok/1.18.46/lombok-1.18.46.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter/5.12.2/junit-jupiter-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.12.2/junit-jupiter-api-5.12.2.jar:/Users/maddy/.m2/repository/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar:/Users/maddy/.m2/repository/org/junit/platform/junit-platform-commons/1.12.2/junit-platform-commons-1.12.2.jar:/Users/maddy/.m2/repository/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-params/5.12.2/junit-jupiter-params-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.12.2/junit-jupiter-engine-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/platform/junit-platform-engine/1.12.2/junit-platform-engine-1.12.2.jar:"/> <property name="surefire.test.class.path" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/test-classes:/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/classes:/Users/maddy/.m2/repository/org/projectlombok/lombok/1.18.46/lombok-1.18.46.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter/5.12.2/junit-jupiter-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.12.2/junit-jupiter-api-5.12.2.jar:/Users/maddy/.m2/repository/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar:/Users/maddy/.m2/repository/org/junit/platform/junit-platform-commons/1.12.2/junit-platform-commons-1.12.2.jar:/Users/maddy/.m2/repository/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-params/5.12.2/junit-jupiter-params-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.12.2/junit-jupiter-engine-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/platform/junit-platform-engine/1.12.2/junit-platform-engine-1.12.2.jar:"/>
@@ -20,8 +20,8 @@
<property name="user.home" value="/Users/maddy"/> <property name="user.home" value="/Users/maddy"/>
<property name="user.language" value="en"/> <property name="user.language" value="en"/>
<property name="java.specification.vendor" value="Oracle Corporation"/> <property name="java.specification.vendor" value="Oracle Corporation"/>
<property name="java.version.date" value="2026-01-20"/> <property name="java.version.date" value="2025-07-15"/>
<property name="java.home" value="/opt/homebrew/Cellar/openjdk/25.0.2/libexec/openjdk.jdk/Contents/Home"/> <property name="java.home" value="/Users/maddy/Library/Java/JavaVirtualMachines/ms-21.0.8/Contents/Home"/>
<property name="file.separator" value="/"/> <property name="file.separator" value="/"/>
<property name="basedir" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib"/> <property name="basedir" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib"/>
<property name="java.vm.compressedOopsMode" value="Zero based"/> <property name="java.vm.compressedOopsMode" value="Zero based"/>
@@ -29,10 +29,10 @@
<property name="java.vm.specification.vendor" value="Oracle Corporation"/> <property name="java.vm.specification.vendor" value="Oracle Corporation"/>
<property name="java.specification.name" value="Java Platform API Specification"/> <property name="java.specification.name" value="Java Platform API Specification"/>
<property name="apple.awt.application.name" value="ForkedBooter"/> <property name="apple.awt.application.name" value="ForkedBooter"/>
<property name="surefire.real.class.path" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/surefire/surefirebooter-20260801204253825_3.jar"/> <property name="surefire.real.class.path" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/surefire/surefirebooter-20260801225315947_3.jar"/>
<property name="sun.management.compiler" value="HotSpot 64-Bit Tiered Compilers"/> <property name="sun.management.compiler" value="HotSpot 64-Bit Tiered Compilers"/>
<property name="ftp.nonProxyHosts" value="local|*.local|169.254/16|*.169.254/16"/> <property name="ftp.nonProxyHosts" value="local|*.local|169.254/16|*.169.254/16"/>
<property name="java.runtime.version" value="25.0.2"/> <property name="java.runtime.version" value="21.0.8+9-LTS"/>
<property name="user.name" value="maddy"/> <property name="user.name" value="maddy"/>
<property name="stdout.encoding" value="UTF-8"/> <property name="stdout.encoding" value="UTF-8"/>
<property name="path.separator" value=":"/> <property name="path.separator" value=":"/>
@@ -40,11 +40,11 @@
<property name="java.runtime.name" value="OpenJDK Runtime Environment"/> <property name="java.runtime.name" value="OpenJDK Runtime Environment"/>
<property name="file.encoding" value="UTF-8"/> <property name="file.encoding" value="UTF-8"/>
<property name="java.vm.name" value="OpenJDK 64-Bit Server VM"/> <property name="java.vm.name" value="OpenJDK 64-Bit Server VM"/>
<property name="java.vendor.version" value="Homebrew"/> <property name="java.vendor.version" value="Microsoft-11933201"/>
<property name="localRepository" value="/Users/maddy/.m2/repository"/> <property name="localRepository" value="/Users/maddy/.m2/repository"/>
<property name="java.vendor.url.bug" value="https://github.com/Homebrew/homebrew-core/issues"/> <property name="java.vendor.url.bug" value="https://github.com/microsoft/openjdk/issues"/>
<property name="java.io.tmpdir" value="/var/folders/1l/36214rdn79755j30lcnmgsqh0000gn/T/"/> <property name="java.io.tmpdir" value="/var/folders/1l/36214rdn79755j30lcnmgsqh0000gn/T/"/>
<property name="java.version" value="25.0.2"/> <property name="java.version" value="21.0.8"/>
<property name="user.dir" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib"/> <property name="user.dir" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib"/>
<property name="os.arch" value="aarch64"/> <property name="os.arch" value="aarch64"/>
<property name="java.vm.specification.name" value="Java Virtual Machine Specification"/> <property name="java.vm.specification.name" value="Java Virtual Machine Specification"/>
@@ -52,13 +52,12 @@
<property name="java.library.path" value="/Users/maddy/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:."/> <property name="java.library.path" value="/Users/maddy/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:."/>
<property name="java.vm.info" value="mixed mode, sharing"/> <property name="java.vm.info" value="mixed mode, sharing"/>
<property name="stderr.encoding" value="UTF-8"/> <property name="stderr.encoding" value="UTF-8"/>
<property name="java.vendor" value="Homebrew"/> <property name="java.vendor" value="Microsoft"/>
<property name="java.vm.version" value="25.0.2"/> <property name="java.vm.version" value="21.0.8+9-LTS"/>
<property name="stdin.encoding" value="UTF-8"/>
<property name="sun.io.unicode.encoding" value="UnicodeBig"/> <property name="sun.io.unicode.encoding" value="UnicodeBig"/>
<property name="socksNonProxyHosts" value="local|*.local|169.254/16|*.169.254/16"/> <property name="socksNonProxyHosts" value="local|*.local|169.254/16|*.169.254/16"/>
<property name="java.class.version" value="69.0"/> <property name="java.class.version" value="65.0"/>
</properties> </properties>
<testcase name="mapsHttpStatusToCanonicalError" classname="lib.models.ErrorDetailsTest" time="0.008"/> <testcase name="mapsHttpStatusToCanonicalError" classname="lib.models.ErrorDetailsTest" time="0.008"/>
<testcase name="createsAReusableErrorContract" classname="lib.models.ErrorDetailsTest" time="0.007"/> <testcase name="createsAReusableErrorContract" classname="lib.models.ErrorDetailsTest" time="0.012"/>
</testsuite> </testsuite>

View File

@@ -1,4 +1,4 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Test set: lib.models.ErrorDetailsTest Test set: lib.models.ErrorDetailsTest
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.024 s -- in lib.models.ErrorDetailsTest Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.028 s -- in lib.models.ErrorDetailsTest

View File

@@ -53,7 +53,7 @@
<c:if test="${pageFormMode!=2}"> <c:if test="${pageFormMode!=2}">
<!-- Dynamic Menu --> <!-- Dynamic Menu -->
<nav class="matrix-shell__navigation" aria-label="Primary navigation"> <nav class="matrix-shell__navigation" aria-label="Primary navigation">
<c:out value="${Sessvals.menuHtml}" escapeXml="false" /> <c:out value="${sessionScope.userSession.menuHtml}" escapeXml="false" />
</nav> </nav>
<!-- --> <!-- -->
</c:if> </c:if>
@@ -133,9 +133,9 @@
<option value="-1" selected >SELECT</option> <option value="-1" selected >SELECT</option>
<c:choose> <c:choose>
<c:when test="${not empty model}"> <c:when test="${not empty model}">
<c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'branch.')}"> <c:forEach items="${model.options['branch.']}" var="option">
<option value="${fn:substringAfter(option.key, 'branch.')}"><c:out value="${option.value}" /></option> <option value="${option.value}"><c:out value="${option.label}" /></option>
</c:if></c:forEach> </c:forEach>
</c:when> </c:when>
<c:otherwise><c:forEach items="${branchlist}" var="brnch"><option value="${brnch[0]}"><c:out value="${brnch[1]}" /></option></c:forEach></c:otherwise> <c:otherwise><c:forEach items="${branchlist}" var="brnch"><option value="${brnch[0]}"><c:out value="${brnch[1]}" /></option></c:forEach></c:otherwise>
</c:choose> </c:choose>
@@ -152,7 +152,7 @@
<select id="product" name="product" style="width:150px" onblur="validate(this,'t','');"> <select id="product" name="product" style="width:150px" onblur="validate(this,'t','');">
<option value="-1" selected >SELECT</option> <option value="-1" selected >SELECT</option>
<c:choose> <c:choose>
<c:when test="${not empty model}"><c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'product.')}"><option value="${fn:substringAfter(option.key, 'product.')}"><c:out value="${option.value}" /></option></c:if></c:forEach></c:when> <c:when test="${not empty model}"><c:forEach items="${model.options['product.']}" var="option"><option value="${option.value}"><c:out value="${option.label}" /></option></c:forEach></c:when>
<c:otherwise><c:forEach items="${prodlist}" var="prod"><option value="${prod[0]}"><c:out value="${prod[1]}" /></option></c:forEach></c:otherwise> <c:otherwise><c:forEach items="${prodlist}" var="prod"><option value="${prod[0]}"><c:out value="${prod[1]}" /></option></c:forEach></c:otherwise>
</c:choose> </c:choose>
</select> </select>
@@ -184,7 +184,7 @@
<select id="apptype" name="apptype" style="width:153px" onchange="ToggleChks((this.value.toUpperCase()!='APPLICANT' && this.value.toUpperCase()!='-1'),'sradd!C0L!soadd!C0L!spadd!C0L!','!C0L!')" onblur="validate(this,'t','');"> <select id="apptype" name="apptype" style="width:153px" onchange="ToggleChks((this.value.toUpperCase()!='APPLICANT' && this.value.toUpperCase()!='-1'),'sradd!C0L!soadd!C0L!spadd!C0L!','!C0L!')" onblur="validate(this,'t','');">
<option value="-1" selected>SELECT</option> <option value="-1" selected>SELECT</option>
<c:choose> <c:choose>
<c:when test="${not empty model}"><c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'applicationType.')}"><option value="${fn:substringAfter(option.key, 'applicationType.')}"><c:out value="${option.value}" /></option></c:if></c:forEach></c:when> <c:when test="${not empty model}"><c:forEach items="${model.options['applicationType.']}" var="option"><option value="${option.value}"><c:out value="${option.label}" /></option></c:forEach></c:when>
<c:otherwise><c:forEach items="${typelist}" var="type"><option value="${type[0]}"><c:out value="${type[1]}" /></option></c:forEach></c:otherwise> <c:otherwise><c:forEach items="${typelist}" var="type"><option value="${type[0]}"><c:out value="${type[1]}" /></option></c:forEach></c:otherwise>
</c:choose> </c:choose>
</select> </select>
@@ -200,7 +200,7 @@
<select id="category" name="category" style="width:133px"> <select id="category" name="category" style="width:133px">
<option value="-1" selected>SELECT</option> <option value="-1" selected>SELECT</option>
<c:choose> <c:choose>
<c:when test="${not empty model}"><c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'category.')}"><option value="${fn:substringAfter(option.key, 'category.')}"><c:out value="${option.value}" /></option></c:if></c:forEach></c:when> <c:when test="${not empty model}"><c:forEach items="${model.options['category.']}" var="option"><option value="${option.value}"><c:out value="${option.label}" /></option></c:forEach></c:when>
<c:otherwise><c:forEach items="${catlist}" var="cat"><option value="${cat[0]}"><c:out value="${cat[1]}" /></option></c:forEach></c:otherwise> <c:otherwise><c:forEach items="${catlist}" var="cat"><option value="${cat[0]}"><c:out value="${cat[1]}" /></option></c:forEach></c:otherwise>
</c:choose> </c:choose>
</select> </select>
@@ -311,7 +311,7 @@
<option value="-1">Select</option> <option value="-1">Select</option>
<option value="Unknown">Unknown</option> <option value="Unknown">Unknown</option>
<c:choose> <c:choose>
<c:when test="${not empty model}"><c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'city.')}"><option value="${fn:substringAfter(option.key, 'city.')}"><c:out value="${option.value}" /></option></c:if></c:forEach></c:when> <c:when test="${not empty model}"><c:forEach items="${model.options['city.']}" var="option"><option value="${option.value}"><c:out value="${option.label}" /></option></c:forEach></c:when>
<c:otherwise><c:forEach items="${citylist}" var="city"><option value="${city[0]}"><c:out value="${city[1]}" /></option></c:forEach></c:otherwise> <c:otherwise><c:forEach items="${citylist}" var="city"><option value="${city[0]}"><c:out value="${city[1]}" /></option></c:forEach></c:otherwise>
</c:choose> </c:choose>
</select> </select>
@@ -429,7 +429,7 @@
<option value="-1">Select</option> <option value="-1">Select</option>
<option value="Unknown">Unknown</option> <option value="Unknown">Unknown</option>
<c:choose> <c:choose>
<c:when test="${not empty model}"><c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'city.')}"><option value="${fn:substringAfter(option.key, 'city.')}"><c:out value="${option.value}" /></option></c:if></c:forEach></c:when> <c:when test="${not empty model}"><c:forEach items="${model.options['city.']}" var="option"><option value="${option.value}"><c:out value="${option.label}" /></option></c:forEach></c:when>
<c:otherwise><c:forEach items="${citylist}" var="city"><option value="${city[0]}"><c:out value="${city[1]}" /></option></c:forEach></c:otherwise> <c:otherwise><c:forEach items="${citylist}" var="city"><option value="${city[0]}"><c:out value="${city[1]}" /></option></c:forEach></c:otherwise>
</c:choose> </c:choose>
</select> </select>
@@ -556,7 +556,7 @@
<option value="-1">Select</option> <option value="-1">Select</option>
<option value="Unknown">Unknown</option> <option value="Unknown">Unknown</option>
<c:choose> <c:choose>
<c:when test="${not empty model}"><c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'city.')}"><option value="${fn:substringAfter(option.key, 'city.')}"><c:out value="${option.value}" /></option></c:if></c:forEach></c:when> <c:when test="${not empty model}"><c:forEach items="${model.options['city.']}" var="option"><option value="${option.value}"><c:out value="${option.label}" /></option></c:forEach></c:when>
<c:otherwise><c:forEach items="${citylist}" var="city"><option value="${city[0]}"><c:out value="${city[1]}" /></option></c:forEach></c:otherwise> <c:otherwise><c:forEach items="${citylist}" var="city"><option value="${city[0]}"><c:out value="${city[1]}" /></option></c:forEach></c:otherwise>
</c:choose> </c:choose>
</select> </select>
@@ -689,8 +689,8 @@
</c:if> </c:if>
<input type="hidden" id="uuid" name="uuid" value="${pageDocumentCaseId}" /> <input type="hidden" id="uuid" name="uuid" value="${pageDocumentCaseId}" />
<input type="hidden" id="case_id" name="case_id" value="" /> <input type="hidden" id="case_id" name="case_id" value="" />
<input type="hidden" id="company_id" name="company_id" value="${Sessvals.getCompanyID()}" /> <input type="hidden" id="company_id" name="company_id" value="${sessionScope.userSession.companyId}" />
<input type="hidden" id="branch_id" name="branch_id" value="${Sessvals.getBranchID()}" /> <input type="hidden" id="branch_id" name="branch_id" value="${sessionScope.userSession.branchId}" />
<input type="hidden" id="status" name="status" value="" /> <input type="hidden" id="status" name="status" value="" />
<!-- --> <!-- -->
<input type="hidden" id="invalidfields" value="0" /> <input type="hidden" id="invalidfields" value="0" />

View File

@@ -6,8 +6,8 @@
<span>Cygnus 1.0</span> <span>Cygnus 1.0</span>
</div> </div>
<div class="matrix-shell__context" aria-label="Current session"> <div class="matrix-shell__context" aria-label="Current session">
<span class="matrix-shell__company"><c:out value="${Sessvals.getCompanyCode()}" /> (<c:out value="${Sessvals.getBranchLocation()}" />)</span> <span class="matrix-shell__company"><c:out value="${sessionScope.userSession.companyCode}" /> (<c:out value="${sessionScope.userSession.branchLocation}" />)</span>
<span class="matrix-shell__user"><c:out value="${Sessvals.getUserDisplayName()}" /> (<c:out value="${Sessvals.getUserGroupName()}" />)</span> <span class="matrix-shell__user"><c:out value="${sessionScope.userSession.userDisplayName}" /> (<c:out value="${sessionScope.userSession.userGroupName}" />)</span>
</div> </div>
</div> </div>
</header> </header>

View File

@@ -5,7 +5,7 @@ import com.cygnus.client.CloudIdentityClient;
import java.time.Duration; import java.time.Duration;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import matrix.nimble.model.Session; import lib.models.UserSession;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClientResponseException; import org.springframework.web.reactive.function.client.WebClientResponseException;
@@ -28,7 +28,7 @@ public class CloudAuthenticationGateway {
this.sessionMapper = sessionMapper; this.sessionMapper = sessionMapper;
} }
public Session authenticate(String loginId, String password) { public UserSession authenticate(String loginId, String password) {
try { try {
Duration blockingTimeout = properties.requestTimeout().plusSeconds(1); Duration blockingTimeout = properties.requestTimeout().plusSeconds(1);
return sessionMapper.map(client.authenticate(loginId, password).block(blockingTimeout)); return sessionMapper.map(client.authenticate(loginId, password).block(blockingTimeout));

View File

@@ -5,6 +5,7 @@ import com.cygnus.client.model.CloudMenuItem;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
import lib.models.UserSession;
import matrix.nimble.model.Session; import matrix.nimble.model.Session;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -20,22 +21,42 @@ public class CloudSessionMapper {
this.menuRenderer = menuRenderer; this.menuRenderer = menuRenderer;
} }
public Session map(CloudIdentitySession source) { public UserSession map(CloudIdentitySession source) {
return UserSession.builder()
.userId(source.userId())
.username(source.loginId())
.userDisplayName(source.displayName())
.userGroupId(source.groupId())
.userGroupName(source.groupName())
.branchId(source.branchId())
.branchName(source.branchName())
.branchCode(source.branchCode())
.branchLocation(source.branchLocation())
.companyId(source.companyId())
.companyName(source.companyName())
.companyCode(source.companyCode())
.loginTime(LEGACY_LOGIN_TIME.format(source.loginTime()))
.menuHtml(menuRenderer.render(toLegacyMenu(source.menu())))
.build();
}
/** Temporary projection used by controllers that have not migrated to UserSession yet. */
public Session toLegacy(UserSession source) {
Session target = new Session(); Session target = new Session();
target.setUserID(Short.toString(source.userId())); target.setUserID(Short.toString(source.getUserId()));
target.setUsername(source.loginId()); target.setUsername(source.getUsername());
target.setUserDisplayName(source.displayName()); target.setUserDisplayName(source.getUserDisplayName());
target.setUserGroupID(Short.toString(source.groupId())); target.setUserGroupID(Short.toString(source.getUserGroupId()));
target.setUserGroupName(source.groupName()); target.setUserGroupName(source.getUserGroupName());
target.setBranchID(Short.toString(source.branchId())); target.setBranchID(Short.toString(source.getBranchId()));
target.setBranchName(source.branchName()); target.setBranchName(source.getBranchName());
target.setBranchCode(source.branchCode()); target.setBranchCode(source.getBranchCode());
target.setBranchLocation(source.branchLocation()); target.setBranchLocation(source.getBranchLocation());
target.setCompanyID(Short.toString(source.companyId())); target.setCompanyID(Short.toString(source.getCompanyId()));
target.setCompanyName(source.companyName()); target.setCompanyName(source.getCompanyName());
target.setCompanyCode(source.companyCode()); target.setCompanyCode(source.getCompanyCode());
target.setLoginTime(LEGACY_LOGIN_TIME.format(source.loginTime())); target.setLoginTime(source.getLoginTime());
target.setMenuHtml(menuRenderer.render(toLegacyMenu(source.menu()))); target.setMenuHtml(source.getMenuHtml());
return target; return target;
} }

View File

@@ -4,7 +4,7 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession; import jakarta.servlet.http.HttpSession;
import lib.constants.ApplicationError; import lib.constants.ApplicationError;
import lib.models.ErrorDetails; import lib.models.ErrorDetails;
import matrix.nimble.model.Session; import lib.models.UserSession;
import matrix.services.commons.CommonErrorService; import matrix.services.commons.CommonErrorService;
import matrix.services.commons.CommonService; import matrix.services.commons.CommonService;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
@@ -26,14 +26,14 @@ public abstract class AbstractAuthenticatedController {
ModelMap model, ModelMap model,
HttpSession httpSession, HttpSession httpSession,
HttpServletResponse response) { HttpServletResponse response) {
Session session = commonService.getSession(httpSession); UserSession session = commonService.getUserSession(httpSession);
if (session == null) { if (session == null) {
return denied(model, response, httpSession, ApplicationError.SESSION_REQUIRED); return denied(model, response, httpSession, ApplicationError.SESSION_REQUIRED);
} }
if (!commonService.hasPageAccess(session, pageRoute)) { if (!commonService.hasPageAccess(session, pageRoute)) {
return denied(model, response, httpSession, ApplicationError.ACCESS_DENIED); return denied(model, response, httpSession, ApplicationError.ACCESS_DENIED);
} }
model.addAttribute(CommonService.SESSION_ATTRIBUTE, session); model.addAttribute(CommonService.USER_SESSION_ATTRIBUTE, session);
return PageAuthorization.granted(session); return PageAuthorization.granted(session);
} }
@@ -47,8 +47,8 @@ public abstract class AbstractAuthenticatedController {
return PageAuthorization.denied(viewName); return PageAuthorization.denied(viewName);
} }
protected record PageAuthorization(Session session, String viewName) { protected record PageAuthorization(UserSession session, String viewName) {
private static PageAuthorization granted(Session session) { private static PageAuthorization granted(UserSession session) {
return new PageAuthorization(session, null); return new PageAuthorization(session, null);
} }

View File

@@ -2,9 +2,11 @@ package matrix.nimble.controller;
import matrix.nimble.cloud.identity.CloudAuthenticationException; import matrix.nimble.cloud.identity.CloudAuthenticationException;
import matrix.nimble.cloud.identity.CloudAuthenticationGateway; import matrix.nimble.cloud.identity.CloudAuthenticationGateway;
import matrix.nimble.cloud.identity.CloudSessionMapper;
import matrix.nimble.model.Login; import matrix.nimble.model.Login;
import matrix.nimble.model.Session; import matrix.nimble.model.Session;
import matrix.services.commons.CommonService; import matrix.services.commons.CommonService;
import lib.models.UserSession;
//servlet libraries //servlet libraries
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
@@ -23,12 +25,15 @@ import org.springframework.web.bind.annotation.SessionAttributes;
public class SessionController { public class SessionController {
private final CloudAuthenticationGateway cloudAuthenticationGateway; private final CloudAuthenticationGateway cloudAuthenticationGateway;
private final CommonService commonService; private final CommonService commonService;
private final CloudSessionMapper cloudSessionMapper;
public SessionController( public SessionController(
CloudAuthenticationGateway cloudAuthenticationGateway, CloudAuthenticationGateway cloudAuthenticationGateway,
CommonService commonService) { CommonService commonService,
CloudSessionMapper cloudSessionMapper) {
this.cloudAuthenticationGateway = cloudAuthenticationGateway; this.cloudAuthenticationGateway = cloudAuthenticationGateway;
this.commonService = commonService; this.commonService = commonService;
this.cloudSessionMapper = cloudSessionMapper;
} }
@RequestMapping(value="login", method={RequestMethod.GET, RequestMethod.POST}) @RequestMapping(value="login", method={RequestMethod.GET, RequestMethod.POST})
public String LoginPage(ModelMap model) public String LoginPage(ModelMap model)
@@ -53,10 +58,12 @@ public class SessionController {
HttpSession httpSession) HttpSession httpSession)
{ {
try { try {
Session cloudSession = cloudAuthenticationGateway.authenticate( UserSession userSession = cloudAuthenticationGateway.authenticate(
login.getLoginid(), login.getPassword()); login.getLoginid(), login.getPassword());
Session cloudSession = cloudSessionMapper.toLegacy(userSession);
model.remove("login"); model.remove("login");
model.addAttribute("Sessvals", cloudSession); model.addAttribute("Sessvals", cloudSession);
commonService.storeUserSession(httpSession, userSession);
commonService.storeSession(httpSession, cloudSession); commonService.storeSession(httpSession, cloudSession);
return "home"; return "home";
} catch (CloudAuthenticationException exception) { } catch (CloudAuthenticationException exception) {

View File

@@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import jakarta.servlet.http.HttpSession; import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import matrix.nimble.controller.AbstractAuthenticatedController; import matrix.nimble.controller.AbstractAuthenticatedController;
import matrix.nimble.model.Session; import lib.models.UserSession;
import matrix.services.commons.CommonService; import matrix.services.commons.CommonService;
import matrix.services.edp.PunchingService; import matrix.services.edp.PunchingService;
import matrix.services.commons.CommonErrorService; import matrix.services.commons.CommonErrorService;
@@ -38,11 +38,10 @@ public class PunchingController extends AbstractAuthenticatedController {
if (!authorization.isGranted()) { if (!authorization.isGranted()) {
return authorization.viewName(); return authorization.viewName();
} }
Session Sessvals = authorization.session(); UserSession userSession = authorization.session();
model.addAttribute("model", punchingService.init( model.addAttribute("model", punchingService.init(
Sessvals.getBranchID(), Sessvals.getUserID(), null, "xxx")); userSession.getBranchId(), userSession.getUserId(), null, null));
model.addAttribute("Sessvals", Sessvals);
return "edp/punching/initcase"; return "edp/punching/initcase";
} }
@@ -58,16 +57,15 @@ public class PunchingController extends AbstractAuthenticatedController {
return authorization.viewName(); return authorization.viewName();
} }
Session session = authorization.session(); UserSession session = authorization.session();
model.addAttribute("model", punchingService.addCase( model.addAttribute("model", punchingService.addCase(
submitted, session.getBranchID(), session.getUserID())); submitted, session.getBranchId(), session.getCompanyId(), session.getUserId()));
model.addAttribute("Sessvals", session);
return "edp/punching/initcase"; return "edp/punching/initcase";
} }
@RequestMapping(value = "caseedit", method = RequestMethod.POST) @RequestMapping(value = "caseedit", method = RequestMethod.POST)
public String editCase( public String editCase(
@RequestParam("PortfolioId") Integer portfolioId, @RequestParam("PortfolioId") Short portfolioId,
@RequestParam("uuid") String documentCaseId, @RequestParam("uuid") String documentCaseId,
ModelMap model, ModelMap model,
HttpSession httpSession, HttpSession httpSession,
@@ -78,10 +76,10 @@ public class PunchingController extends AbstractAuthenticatedController {
return authorization.viewName(); return authorization.viewName();
} }
Session session = authorization.session(); UserSession session = authorization.session();
model.addAttribute("model", punchingService.editCase( model.addAttribute("model", punchingService.editCase(
portfolioId, documentCaseId, session.getBranchID(), session.getUserID())); portfolioId, documentCaseId, session.getBranchId(),
model.addAttribute("Sessvals", session); session.getCompanyId(), session.getUserId()));
return "edp/punching/initcase"; return "edp/punching/initcase";
} }
} }

View File

@@ -3,6 +3,7 @@ package matrix.services.commons;
import com.cygnus.db.CygnusDbExecutor; import com.cygnus.db.CygnusDbExecutor;
import jakarta.servlet.http.HttpSession; import jakarta.servlet.http.HttpSession;
import lib.models.Option; import lib.models.Option;
import lib.models.UserSession;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -15,6 +16,7 @@ import org.springframework.stereotype.Service;
@Service @Service
public class CommonService { public class CommonService {
public static final String SESSION_ATTRIBUTE = "Sessvals"; public static final String SESSION_ATTRIBUTE = "Sessvals";
public static final String USER_SESSION_ATTRIBUTE = "userSession";
private static final Pattern MENU_COMMAND = Pattern.compile( private static final Pattern MENU_COMMAND = Pattern.compile(
"SubmitMenuCommand\\(\\s*'([^']+)'\\s*,", "SubmitMenuCommand\\(\\s*'([^']+)'\\s*,",
@@ -46,6 +48,20 @@ public class CommonService {
httpSession.setAttribute(SESSION_ATTRIBUTE, Objects.requireNonNull(session, "session")); httpSession.setAttribute(SESSION_ATTRIBUTE, Objects.requireNonNull(session, "session"));
} }
public UserSession getUserSession(HttpSession httpSession) {
if (httpSession == null) {
return null;
}
Object value = httpSession.getAttribute(USER_SESSION_ATTRIBUTE);
return value instanceof UserSession session ? session : null;
}
public void storeUserSession(HttpSession httpSession, UserSession session) {
Objects.requireNonNull(httpSession, "httpSession");
httpSession.setAttribute(
USER_SESSION_ATTRIBUTE, Objects.requireNonNull(session, "session"));
}
public boolean hasPageAccess(HttpSession httpSession, String pageRoute) { public boolean hasPageAccess(HttpSession httpSession, String pageRoute) {
return hasPageAccess(getSession(httpSession), pageRoute); return hasPageAccess(getSession(httpSession), pageRoute);
} }
@@ -69,6 +85,29 @@ public class CommonService {
return false; return false;
} }
public boolean hasPageAccess(UserSession session, String pageRoute) {
return session != null && hasPageAccess(session.getMenuHtml(), pageRoute);
}
private boolean hasPageAccess(String menuHtml, String pageRoute) {
if (menuHtml == null) {
return false;
}
String requiredRoute = normalizeRoute(pageRoute);
if (requiredRoute.isEmpty()) {
return false;
}
Matcher matcher = MENU_COMMAND.matcher(menuHtml);
while (matcher.find()) {
if (normalizeRoute(matcher.group(1)).equals(requiredRoute)) {
return true;
}
}
return false;
}
private String normalizeRoute(String route) { private String normalizeRoute(String route) {
if (route == null) { if (route == null) {
return ""; return "";

View File

@@ -1,5 +1,6 @@
package matrix.services.edp; package matrix.services.edp;
import com.cygnus.db.SqlArrayParameter;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@@ -13,7 +14,6 @@ import lib.models.ErrorDetails;
import lib.models.Option; import lib.models.Option;
import lib.constants.ApplicationError; import lib.constants.ApplicationError;
import matrix.nimble.edp.punching.model.PunchingHandler; import matrix.nimble.edp.punching.model.PunchingHandler;
import matrix.nimble.utilities.CommonFunctions;
import matrix.nimble.utilities.GlobalClass; import matrix.nimble.utilities.GlobalClass;
import matrix.services.commons.CommonService; import matrix.services.commons.CommonService;
@@ -25,8 +25,15 @@ public class PunchingService {
private static final String PRODUCT = "product."; private static final String PRODUCT = "product.";
private static final String CITY = "city."; private static final String CITY = "city.";
private static final String APPLICATION_TYPE = "applicationType."; private static final String APPLICATION_TYPE = "applicationType.";
private static final String DATABASE_APPLICATION_TYPE = "apptype.";
private static final String CATEGORY = "category."; private static final String CATEGORY = "category.";
private static final Short ACTIVE = Short.valueOf((short) 1);
private static final SqlArrayParameter GENERAL_OPTION_TYPES =
SqlArrayParameter.text("CITY", "APPTYPE");
private static final SqlArrayParameter PORTFOLIO_OPTION_TYPES =
SqlArrayParameter.text("CATEGORY", "PRODUCT");
private final CommonService commonService; private final CommonService commonService;
public PunchingService(CommonService commonService) { public PunchingService(CommonService commonService) {
@@ -34,8 +41,8 @@ public class PunchingService {
} }
public CasePunching init( public CasePunching init(
String branchId, Short branchId,
String userId, Short userId,
String verificationCaseId, String verificationCaseId,
String documentCaseId) { String documentCaseId) {
PunchingHandler punchingHandler = new PunchingHandler(); PunchingHandler punchingHandler = new PunchingHandler();
@@ -43,16 +50,15 @@ public class PunchingService {
CasePunching casePunching = new CasePunching(); CasePunching casePunching = new CasePunching();
Map<String, List<Option>> options = new LinkedHashMap<>(); Map<String, List<Option>> options = new LinkedHashMap<>();
Short databaseBranchId = Short.valueOf(branchId.trim());
List<Option> portfolios = commonService.getOptions( List<Option> portfolios = commonService.getOptions(
3, new Object[] { databaseBranchId, Short.valueOf((short) 1) }); 3, new Object[] { branchId, ACTIVE });
addOptions(options, PORTFOLIO, portfolios); addOptions(options, PORTFOLIO, portfolios);
casePunching.setOptions(Collections.unmodifiableMap(options)); casePunching.setOptions(freezeOptions(options));
casePunching.setVisibleSections(List.of()); casePunching.setVisibleSections(List.of());
casePunching.setPortfolioId(-1); casePunching.setPortfolioId((short) -1);
casePunching.setFormMode(0); casePunching.setFormMode(0);
casePunching.setUserId(userId); casePunching.setUserId(Short.toString(userId));
casePunching.setDynamicFields(""); casePunching.setDynamicFields("");
casePunching.setDynamicHtml(""); casePunching.setDynamicHtml("");
casePunching.setVerificationCaseId(verificationCaseId); casePunching.setVerificationCaseId(verificationCaseId);
@@ -62,17 +68,18 @@ public class PunchingService {
public CasePunching addCase( public CasePunching addCase(
CasePunching submitted, CasePunching submitted,
String branchIds, Short branchId,
String userId) { Short companyId,
Short userId) {
CasePunching result = new CasePunching(); CasePunching result = new CasePunching();
result.setPortfolioId(submitted.getPortfolioId()); result.setPortfolioId(submitted.getPortfolioId());
result.setFormMode(1); result.setFormMode(1);
result.setUserId(userId); result.setUserId(Short.toString(userId));
result.setVerificationCaseId(submitted.getVerificationCaseId()); result.setVerificationCaseId(submitted.getVerificationCaseId());
result.setDocumentCaseId("xxx"); result.setDocumentCaseId("xxx");
if (submitted.getPortfolioId() == null || submitted.getPortfolioId() <= 0) { if (submitted.getPortfolioId() == null || submitted.getPortfolioId() <= 0) {
result.setOptions(Collections.emptyMap()); result.setOptions(Map.of());
result.setVisibleSections(List.of()); result.setVisibleSections(List.of());
result.setDynamicFields(""); result.setDynamicFields("");
result.setDynamicHtml(""); result.setDynamicHtml("");
@@ -80,11 +87,10 @@ public class PunchingService {
return result; return result;
} }
String portfolioId = submitted.getPortfolioId().toString(); Short portfolioId = submitted.getPortfolioId();
PunchingHandler punchingHandler = new PunchingHandler(); PunchingHandler punchingHandler = new PunchingHandler();
CommonFunctions commonFunctions = new CommonFunctions();
punchingHandler.setErrCode("1001"); punchingHandler.setErrCode("1001");
punchingHandler.setPortfolioid(portfolioId); punchingHandler.setPortfolioid(Short.toString(portfolioId));
punchingHandler.setProcessFlag(true); punchingHandler.setProcessFlag(true);
punchingHandler.DynamicHtml("10"); punchingHandler.DynamicHtml("10");
@@ -101,65 +107,40 @@ public class PunchingService {
result.setErrorDetails(new ErrorDetails(ApplicationError.INTERNAL_SERVER_ERROR)); result.setErrorDetails(new ErrorDetails(ApplicationError.INTERNAL_SERVER_ERROR));
} }
Map<String, String> options = new LinkedHashMap<>(); result.setOptions(loadOptions(branchId, companyId, portfolioId));
punchingHandler.GetDDValues(3, branchIds.split(GlobalClass.ColDelim));
addOptions(options, PORTFOLIO, punchingHandler.getOptionvals());
punchingHandler.GetDDValues(4, new String[] { portfolioId });
addOptions(options, BRANCH, punchingHandler.getOptionvals());
punchingHandler.GetDDValues(5,
(branchIds + GlobalClass.ColDelim
+ "op.description='CITY' or op.description='APPTYPE'"
+ GlobalClass.ColDelim).split(GlobalClass.ColDelim));
String[][] generalOptions = punchingHandler.getOptionvals();
if (generalOptions != null) {
addOptions(options, CITY,
commonFunctions.GetSubArray("CITY", 2, generalOptions));
addOptions(options, APPLICATION_TYPE,
commonFunctions.GetSubArray("APPTYPE", 2, generalOptions));
}
punchingHandler.GetDDValues(70,
(portfolioId + GlobalClass.ColDelim
+ "op.description='CATEGORY' or op.description='PRODUCT'"
+ GlobalClass.ColDelim).split(GlobalClass.ColDelim));
String[][] portfolioOptions = punchingHandler.getOptionvals();
if (portfolioOptions != null) {
addOptions(options, PRODUCT,
commonFunctions.GetSubArray("PRODUCT", 2, portfolioOptions));
addOptions(options, CATEGORY,
commonFunctions.GetSubArray("CATEGORY", 2, portfolioOptions));
}
result.setOptionsl(Collections.unmodifiableMap(options));
return result; return result;
} }
Map<String, List<Option>> loadOptions(
Short branchId, Short companyId, Short portfolioId) {
Map<String, List<Option>> options = new LinkedHashMap<>();
addOptions(options, PORTFOLIO, commonService.getOptions(
3, new Object[] {branchId, ACTIVE}));
addOptions(options, BRANCH, commonService.getOptions(
4, new Object[] {portfolioId, ACTIVE}));
addGroupedOptions(options, commonService.getOptions(
5, new Object[] {companyId, GENERAL_OPTION_TYPES}));
addGroupedOptions(options, commonService.getOptions(
70, new Object[] {portfolioId, PORTFOLIO_OPTION_TYPES}));
return freezeOptions(options);
}
public CasePunching editCase( public CasePunching editCase(
Integer portfolioId, Short portfolioId,
String documentCaseId, String documentCaseId,
String branchIds, Short branchId,
String userId) { Short companyId,
Short userId) {
CasePunching submitted = new CasePunching(); CasePunching submitted = new CasePunching();
submitted.setPortfolioId(portfolioId); submitted.setPortfolioId(portfolioId);
submitted.setDocumentCaseId(documentCaseId); submitted.setDocumentCaseId(documentCaseId);
CasePunching result = addCase(submitted, branchIds, userId); CasePunching result = addCase(submitted, branchId, companyId, userId);
result.setFormMode(2); result.setFormMode(2);
result.setDocumentCaseId(documentCaseId); result.setDocumentCaseId(documentCaseId);
return result; return result;
} }
private void addOptions(Map<String, String> options, String prefix, String[][] values) {
if (values == null) {
return;
}
for (String[] value : values) {
if (value != null && value.length >= 2 && value[0] != null) {
options.put(prefix + value[0], value[1] == null ? "" : value[1]);
}
}
}
private void addOptions(Map<String, List<Option>> options, String prefix, List<Option> values) { private void addOptions(Map<String, List<Option>> options, String prefix, List<Option> values) {
if (values == null || values.isEmpty()) { if (values == null || values.isEmpty()) {
return; return;
@@ -178,6 +159,45 @@ public class PunchingService {
} }
} }
private void addGroupedOptions(Map<String, List<Option>> options, List<Option> values) {
if (values == null || values.isEmpty()) {
return;
}
for (Option value : values) {
if (value == null || value.getValue() == null) {
continue;
}
String group = normalizeGroup(value.getGroup());
if (group == null) {
continue;
}
options.computeIfAbsent(group, ignored -> new java.util.ArrayList<>()).add(value);
}
}
private String normalizeGroup(String group) {
if (group == null || group.isBlank()) {
return null;
}
String normalized = group.trim();
if (DATABASE_APPLICATION_TYPE.equalsIgnoreCase(normalized)) {
return APPLICATION_TYPE;
}
if (CITY.equalsIgnoreCase(normalized)) return CITY;
if (CATEGORY.equalsIgnoreCase(normalized)) return CATEGORY;
if (PRODUCT.equalsIgnoreCase(normalized)) return PRODUCT;
return null;
}
private Map<String, List<Option>> freezeOptions(Map<String, List<Option>> options) {
if (options.isEmpty()) {
return Map.of();
}
Map<String, List<Option>> immutable = new LinkedHashMap<>(options.size());
options.forEach((group, values) -> immutable.put(group, List.copyOf(values)));
return Collections.unmodifiableMap(immutable);
}
private List<String> toVisibleSections(String sections) { private List<String> toVisibleSections(String sections) {
if (sections == null || sections.isBlank()) { if (sections == null || sections.isBlank()) {
return List.of(); return List.of();

View File

@@ -310,7 +310,8 @@ class RoleVisibleBatchMigrationTest {
Path.of("build/WebContent/WEB-INF/app/operation/tools").resolve(page)); Path.of("build/WebContent/WEB-INF/app/operation/tools").resolve(page));
assertTrue(content.contains("matrix-shell matrix-tool-workspace"), page); assertTrue(content.contains("matrix-shell matrix-tool-workspace"), page);
assertTrue(content.contains("tool-workspace-v3.css"), page); assertTrue(content.contains("tool-workspace-v3.css"), page);
assertTrue(content.contains("Sessvals.menuHtml"), page); assertTrue(content.contains("Sessvals.menuHtml")
|| content.contains("sessionScope.userSession.menuHtml"), page);
assertFalse(content.contains("z-index:-1"), page); assertFalse(content.contains("z-index:-1"), page);
assertFalse(content.contains("centerDivBoth(\"formcontainer\""), page); assertFalse(content.contains("centerDivBoth(\"formcontainer\""), page);
} }
@@ -505,7 +506,8 @@ class RoleVisibleBatchMigrationTest {
String content = Files.readString(punching.resolve(page)); String content = Files.readString(punching.resolve(page));
assertTrue(content.contains("matrix-tool-workspace matrix-punch-workspace"), page); assertTrue(content.contains("matrix-tool-workspace matrix-punch-workspace"), page);
assertTrue(content.contains("punch-workspace-v3.css"), page); assertTrue(content.contains("punch-workspace-v3.css"), page);
assertTrue(content.contains("Sessvals.menuHtml"), page); assertTrue(content.contains("Sessvals.menuHtml")
|| content.contains("sessionScope.userSession.menuHtml"), page);
assertFalse(content.contains("z-index:-1"), page); assertFalse(content.contains("z-index:-1"), page);
assertFalse(content.contains("centerDivBoth(\"formcontainer\""), page); assertFalse(content.contains("centerDivBoth(\"formcontainer\""), page);
} }

View File

@@ -8,13 +8,13 @@ import com.cygnus.client.model.CloudIdentitySession;
import com.cygnus.client.model.CloudMenuItem; import com.cygnus.client.model.CloudMenuItem;
import java.time.Instant; import java.time.Instant;
import java.util.List; import java.util.List;
import matrix.nimble.model.Session; import lib.models.UserSession;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
class CloudSessionMapperTest { class CloudSessionMapperTest {
@Test @Test
void mapsCloudIdentityAndStructuredMenuToLegacySession() { void mapsCloudIdentityAndStructuredMenuToTypedSession() {
CloudIdentitySession identity = new CloudIdentitySession( CloudIdentitySession identity = new CloudIdentitySession(
(short) 17, (short) 17,
"maddy", "maddy",
@@ -37,9 +37,9 @@ class CloudSessionMapperTest {
(short) 11, "Scanning", "scanreporting", (short) 10, (short) 11, "Scanning", "scanreporting", (short) 10,
(short) 1, "111", "_parent", ""))); (short) 1, "111", "_parent", "")));
Session session = new CloudSessionMapper(new SessionMenuRenderer()).map(identity); UserSession session = new CloudSessionMapper(new SessionMenuRenderer()).map(identity);
assertEquals("17", session.getUserID()); assertEquals((short) 17, session.getUserId());
assertEquals("maddy", session.getUsername()); assertEquals("maddy", session.getUsername());
assertEquals("Operations", session.getUserGroupName()); assertEquals("Operations", session.getUserGroupName());
assertEquals("Mayapuri", session.getBranchName()); assertEquals("Mayapuri", session.getBranchName());
@@ -49,4 +49,19 @@ class CloudSessionMapperTest {
assertTrue(session.getMenuHtml().contains("Scanning")); assertTrue(session.getMenuHtml().contains("Scanning"));
assertTrue(session.getMenuHtml().contains("scanreporting")); assertTrue(session.getMenuHtml().contains("scanreporting"));
} }
@Test
void createsLegacyProjectionWithoutLosingIdentityValues() {
CloudIdentitySession identity = new CloudIdentitySession(
(short) 17, "maddy", "Maddy", (short) 5, "Operations",
(short) 9, "Mayapuri", "MYP", "Delhi", (short) 2,
"Matrix", "MCR", Instant.parse("2026-07-23T06:30:00Z"), List.of());
CloudSessionMapper mapper = new CloudSessionMapper(new SessionMenuRenderer());
matrix.nimble.model.Session legacy = mapper.toLegacy(mapper.map(identity));
assertEquals("17", legacy.getUserID());
assertEquals("9", legacy.getBranchID());
assertEquals("2", legacy.getCompanyID());
}
} }

View File

@@ -4,7 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import matrix.nimble.model.Session; import lib.models.UserSession;
import matrix.services.commons.CommonErrorService; import matrix.services.commons.CommonErrorService;
import matrix.services.commons.CommonService; import matrix.services.commons.CommonService;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -20,8 +20,8 @@ class AbstractAuthenticatedControllerTest {
@Test @Test
void grantsAConfiguredMenuRoute() { void grantsAConfiguredMenuRoute() {
MockHttpSession httpSession = new MockHttpSession(); MockHttpSession httpSession = new MockHttpSession();
Session session = sessionWithRoute("initview"); UserSession session = sessionWithRoute("initview");
commonService.storeSession(httpSession, session); commonService.storeUserSession(httpSession, session);
AbstractAuthenticatedController.PageAuthorization result = controller.authorize( AbstractAuthenticatedController.PageAuthorization result = controller.authorize(
"initview", new ModelMap(), httpSession, new MockHttpServletResponse()); "initview", new ModelMap(), httpSession, new MockHttpServletResponse());
@@ -39,7 +39,7 @@ class AbstractAuthenticatedControllerTest {
assertEquals(401, noSessionResponse.getStatus()); assertEquals(401, noSessionResponse.getStatus());
MockHttpSession httpSession = new MockHttpSession(); MockHttpSession httpSession = new MockHttpSession();
commonService.storeSession(httpSession, sessionWithRoute("dashboard")); commonService.storeUserSession(httpSession, sessionWithRoute("dashboard"));
MockHttpServletResponse deniedResponse = new MockHttpServletResponse(); MockHttpServletResponse deniedResponse = new MockHttpServletResponse();
AbstractAuthenticatedController.PageAuthorization denied = controller.authorize( AbstractAuthenticatedController.PageAuthorization denied = controller.authorize(
"initview", new ModelMap(), httpSession, deniedResponse); "initview", new ModelMap(), httpSession, deniedResponse);
@@ -47,11 +47,11 @@ class AbstractAuthenticatedControllerTest {
assertEquals(403, deniedResponse.getStatus()); assertEquals(403, deniedResponse.getStatus());
} }
private Session sessionWithRoute(String route) { private UserSession sessionWithRoute(String route) {
Session session = new Session(); return UserSession.builder()
session.setMenuHtml("<a onclick=\"SubmitMenuCommand('" + route .menuHtml("<a onclick=\"SubmitMenuCommand('" + route
+ "','_parent','MenuForm','')\">Page</a>"); + "','_parent','MenuForm','')\">Page</a>")
return session; .build();
} }
private static final class TestController extends AbstractAuthenticatedController { private static final class TestController extends AbstractAuthenticatedController {

View File

@@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import matrix.nimble.model.Session; import matrix.nimble.model.Session;
import lib.models.UserSession;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpSession; import org.springframework.mock.web.MockHttpSession;
@@ -21,6 +22,17 @@ class CommonServiceTest {
assertSame(session, service.getSession(httpSession)); assertSame(session, service.getSession(httpSession));
} }
@Test
void storesAndReadsTypedUserSession() {
MockHttpSession httpSession = new MockHttpSession();
UserSession session = typedSessionWithMenu("initview");
service.storeUserSession(httpSession, session);
assertSame(session, service.getUserSession(httpSession));
assertTrue(service.hasPageAccess(session, "initview"));
}
@Test @Test
void grantsOnlyAnExactMenuCommandRoute() { void grantsOnlyAnExactMenuCommandRoute() {
Session session = sessionWithMenu("/matrix/ver/initview?source=menu"); Session session = sessionWithMenu("/matrix/ver/initview?source=menu");
@@ -42,4 +54,11 @@ class CommonServiceTest {
+ "','_parent','MenuForm','')\">Punching</a>"); + "','_parent','MenuForm','')\">Punching</a>");
return session; return session;
} }
private UserSession typedSessionWithMenu(String route) {
return UserSession.builder()
.menuHtml("<a onclick=\"SubmitMenuCommand('" + route
+ "','_parent','MenuForm','')\">Punching</a>")
.build();
}
} }

View File

@@ -0,0 +1,76 @@
package matrix.services.edp;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.cygnus.db.SqlArrayParameter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import lib.models.Option;
import matrix.services.commons.CommonService;
import org.junit.jupiter.api.Test;
class PunchingServiceTest {
@Test
void loadsParameterizedOptionsAndNormalizesApplicationTypeGroup() {
RecordingCommonService commonService = new RecordingCommonService();
PunchingService service = new PunchingService(commonService);
Map<String, List<Option>> options = service.loadOptions((short) 5, (short) 1, (short) 38);
assertEquals(List.of(3, 4, 5, 70),
commonService.calls.stream().map(Call::queryId).toList());
assertArrayEquals(new Object[] {(short) 5, (short) 1},
commonService.calls.get(0).parameters());
assertArrayEquals(new Object[] {(short) 38, (short) 1},
commonService.calls.get(1).parameters());
assertEquals((short) 1, commonService.calls.get(2).parameters()[0]);
assertArrayEquals(new Object[] {"CITY", "APPTYPE"},
((SqlArrayParameter) commonService.calls.get(2).parameters()[1]).values());
assertEquals((short) 38, commonService.calls.get(3).parameters()[0]);
assertArrayEquals(new Object[] {"CATEGORY", "PRODUCT"},
((SqlArrayParameter) commonService.calls.get(3).parameters()[1]).values());
assertEquals("Portfolio", options.get("portfolio.").getFirst().getLabel());
assertEquals("Branch", options.get("branch.").getFirst().getLabel());
assertEquals("City", options.get("city.").getFirst().getLabel());
assertEquals("Applicant", options.get("applicationType.").getFirst().getLabel());
assertEquals("Category", options.get("category.").getFirst().getLabel());
assertEquals("Product", options.get("product.").getFirst().getLabel());
assertThrows(UnsupportedOperationException.class,
() -> options.put("other.", List.of()));
}
private static final class RecordingCommonService extends CommonService {
private final List<Call> calls = new ArrayList<>();
@Override
public List<Option> getOptions(Integer queryId, Object[] queryParams) {
calls.add(new Call(queryId, queryParams.clone()));
return switch (queryId) {
case 3 -> List.of(option(38, "Portfolio", "portfolio."));
case 4 -> List.of(option(7, "Branch", "branch."));
case 5 -> List.of(
option("DEL", "City", "city."),
option("APPLICANT", "Applicant", "apptype."));
case 70 -> List.of(
option("DIRECTOR", "Category", "category."),
option("AUTO", "Product", "product."));
default -> List.of();
};
}
}
private static Option option(Object value, String label, String group) {
Option option = new Option();
option.setValue(value);
option.setLabel(label);
option.setGroup(group);
return option;
}
private record Call(int queryId, Object[] parameters) {}
}