11 Commits

152 changed files with 3818 additions and 5261 deletions

3
.gitignore vendored
View File

@@ -30,7 +30,8 @@
/.nb-gradle/
/cygnus-onprem-app/target
/cygnus-cloud-client/target
/cygnus-installer/src/test
/cygnus-cloud-service/target
/cygnus-installer/src/target
/cygnus-installer/target
/cygnus-onprem-db/target
/cygnus-lib/target

3
.vscode/launch.json vendored
View File

@@ -61,6 +61,7 @@
"REDIS_PASSWORD": "M@triXR3d1s@6202",
"REDIS_DATABASE": "1",
"REDIS_SSL": "false",
"CYGNUS_QUERY_CACHE_ENABLED": "false",
"CYGNUS_CLOUD_BASE_URL": "http://localhost:8090",
"CYGNUS_TOKEN_URL": "http://localhost:8090/oauth2/token",
"CYGNUS_CLIENT_ID": "matrix",
@@ -68,6 +69,8 @@
"CYGNUS_CLIENT_ASSERTION": "file:${workspaceFolder}/config/clients/matrix/matrix-matrix-delhi-cygnus-01-assertion.jwt",
"CYGNUS_LOGIN_KEY_ID": "cygnus-login-2026-01",
"CYGNUS_LOGIN_PUBLIC_KEY": "file:${workspaceFolder}/config/keys/login-public.pem",
"CYGNUS_PAYLOAD_PRIVATE_KEY": "file:${workspaceFolder}/config/keys/case-save-private.pem",
"CYGNUS_PAYLOAD_PUBLIC_KEY": "file:${workspaceFolder}/config/keys/case-save-public.pem",
"CYGNUS_CLOUD_REQUEST_TIMEOUT": "PT10S",
"CYGNUS_TOKEN_REFRESH_SKEW": "PT30S"
},

View File

@@ -62,4 +62,15 @@ public class CloudIdentityClient {
.bodyToMono(CloudQueryResponse.class))
.timeout(properties.requestTimeout());
}
public Mono<CloudQueryResponse> fetchQuery(String queryKey) {
return tokenProvider.accessToken()
.flatMap(token -> webClient.get()
.uri(properties.baseUri().resolve("/api/v1/queries/key/" + queryKey))
.header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(CloudQueryResponse.class))
.timeout(properties.requestTimeout());
}
}

View File

@@ -25,4 +25,10 @@ public class CloudQueryController {
return repository.findEnabled(queryId)
.switchIfEmpty(Mono.error(new QueryNotFoundException(queryId)));
}
@GetMapping("/key/{queryKey}")
public Mono<CloudQuery> queryByKey(@PathVariable String queryKey) {
return repository.findEnabled(queryKey)
.switchIfEmpty(Mono.error(new QueryNotFoundException(queryKey)));
}
}

View File

@@ -10,8 +10,10 @@ public class QueryCatalogRepository {
private static final String INITIALIZE = """
CREATE SCHEMA IF NOT EXISTS platform;
CREATE SEQUENCE IF NOT EXISTS platform.application_query_id_seq;
CREATE TABLE IF NOT EXISTS platform.application_query (
query_id integer PRIMARY KEY,
query_id integer PRIMARY KEY DEFAULT nextval('platform.application_query_id_seq'),
query_key varchar(100),
query_text text NOT NULL,
enabled boolean NOT NULL DEFAULT true,
created_at timestamptz NOT NULL DEFAULT current_timestamp,
@@ -20,7 +22,15 @@ public class QueryCatalogRepository {
CHECK (query_id > 0),
CONSTRAINT ck_platform_application_query_text
CHECK (length(btrim(query_text)) > 0)
)
);
ALTER TABLE platform.application_query
ADD COLUMN IF NOT EXISTS query_key varchar(100);
ALTER TABLE platform.application_query ALTER COLUMN query_id
SET DEFAULT nextval('platform.application_query_id_seq');
CREATE UNIQUE INDEX IF NOT EXISTS ux_platform_application_query_key
ON platform.application_query (query_key) WHERE query_key IS NOT NULL;
SELECT setval('platform.application_query_id_seq',
greatest(coalesce((SELECT max(query_id) FROM platform.application_query), 0) + 1, 1), false)
""";
private static final String FIND = """
SELECT query_id, query_text
@@ -28,6 +38,12 @@ public class QueryCatalogRepository {
WHERE query_id = $1
AND enabled = true
""";
private static final String FIND_BY_KEY = """
SELECT query_id, query_text
FROM platform.application_query
WHERE query_key = $1
AND enabled = true
""";
private final ReactiveDatabaseClient database;
public QueryCatalogRepository(ReactiveDatabaseClient database) {
@@ -45,4 +61,11 @@ public class QueryCatalogRepository {
.map(row -> new CloudQuery(
row.getInteger("query_id"), row.getString("query_text")));
}
public Mono<CloudQuery> findEnabled(String queryKey) {
return database.preparedQuery(FIND_BY_KEY, Tuple.of(queryKey))
.flatMapMany(rows -> reactor.core.publisher.Flux.fromIterable(rows))
.next()
.map(row -> new CloudQuery(row.getInteger("query_id"), row.getString("query_text")));
}
}

View File

@@ -9,4 +9,8 @@ public class QueryNotFoundException extends RuntimeException {
public QueryNotFoundException(int queryId) {
super("Query was not found: " + queryId);
}
public QueryNotFoundException(String queryKey) {
super("Query was not found: " + queryKey);
}
}

View File

@@ -1,7 +1,9 @@
CREATE SCHEMA IF NOT EXISTS platform;
CREATE SEQUENCE IF NOT EXISTS platform.application_query_id_seq;
CREATE TABLE IF NOT EXISTS platform.application_query (
query_id integer PRIMARY KEY,
query_id integer PRIMARY KEY DEFAULT nextval('platform.application_query_id_seq'),
query_key varchar(100),
query_text text NOT NULL,
enabled boolean NOT NULL DEFAULT true,
created_at timestamptz NOT NULL DEFAULT current_timestamp,
@@ -11,3 +13,11 @@ CREATE TABLE IF NOT EXISTS platform.application_query (
CONSTRAINT ck_platform_application_query_text
CHECK (length(btrim(query_text)) > 0)
);
ALTER TABLE platform.application_query
ADD COLUMN IF NOT EXISTS query_key varchar(100);
CREATE UNIQUE INDEX IF NOT EXISTS ux_platform_application_query_key
ON platform.application_query (query_key) WHERE query_key IS NOT NULL;
ALTER TABLE platform.application_query ALTER COLUMN query_id
SET DEFAULT nextval('platform.application_query_id_seq');
SELECT setval('platform.application_query_id_seq',
greatest(coalesce((SELECT max(query_id) FROM platform.application_query), 0) + 1, 1), false);

View File

@@ -0,0 +1,11 @@
-- Stable query key; query_id is generated by PostgreSQL.
BEGIN;
INSERT INTO platform.application_query(query_key, query_text, enabled, created_at, updated_at, ismigrated)
VALUES ('APPLICATION_SAVE',
'procedure!C0L!select * from public.save_application_details(?::jsonb,?::smallint,?::smallint,?::smallint)',
true, clock_timestamp(), clock_timestamp(), true)
ON CONFLICT (query_key) WHERE query_key IS NOT NULL DO UPDATE SET
query_text=excluded.query_text, enabled=true, updated_at=clock_timestamp(), ismigrated=true;
COMMIT;

View File

@@ -1,9 +1,7 @@
package lib.constants;
import java.util.Arrays;
/** Canonical user-facing errors shared by Cygnus applications. */
public enum ApplicationError {
/** Canonical user-facing messages shared by Cygnus applications. */
public enum ApplicationMessage {
BAD_REQUEST(400, "HTTP-400", "Invalid request",
"Cygnus could not process the submitted request.",
"Review the supplied information and try again."),
@@ -28,6 +26,28 @@ public enum ApplicationError {
TOO_MANY_REQUESTS(429, "HTTP-429", "Too many requests",
"Cygnus has received too many requests in a short period.",
"Wait briefly before trying again."),
PAYLOAD_INVALID(400, "REQ-4001", "Invalid request details",
"The encrypted request could not be verified.",
"Refresh the page and submit the form again."),
APPLICATION_VALIDATION_FAILED(422, "APP-4221", "Application validation failed",
"One or more application fields contain invalid information.",
"Correct the highlighted fields and submit the application again."),
APPLICATION_ACCESS_DENIED(403, "APP-4031", "Application access denied",
"The selected portfolio or application is not available to your account.",
"Select an authorized portfolio or contact your administrator."),
APPLICATION_SAVE_CONFLICT(409, "APP-4091", "Application save conflict",
"This request was already processed or the application changed.",
"Refresh the application before submitting it again."),
APPLICATION_SAVED(200, "APP-2001", "Application saved",
"The application details were saved successfully.", ""),
APPLICATIONS_LOADED(200, "APP-2002", "Applications loaded",
"The application records were loaded successfully.", ""),
APPLICATION_LOAD_FAILED(500, "APP-5002", "Applications could not be loaded",
"Cygnus could not load the application details.",
"Try again. If the issue continues, share the reference ID with support."),
APPLICATION_SAVE_FAILED(500, "APP-5001", "Application could not be saved",
"Cygnus could not save the application details.",
"Try again. If the issue continues, share the reference ID with support."),
INTERNAL_SERVER_ERROR(500, "HTTP-500", "Something went wrong",
"Cygnus could not complete your request.",
"Try again. If the issue continues, share the reference ID with support."),
@@ -47,7 +67,7 @@ public enum ApplicationError {
private final String message;
private final String description;
ApplicationError(
ApplicationMessage(
int httpStatus, String code, String title, String message, String description) {
this.httpStatus = httpStatus;
this.code = code;
@@ -56,11 +76,21 @@ public enum ApplicationError {
this.description = description;
}
public static ApplicationError fromHttpStatus(int status) {
return Arrays.stream(values())
.filter(error -> error.httpStatus == status)
.findFirst()
.orElse(INTERNAL_SERVER_ERROR);
public static ApplicationMessage fromHttpStatus(int status) {
return switch (status) {
case 400 -> BAD_REQUEST;
case 401 -> SESSION_REQUIRED;
case 403 -> ACCESS_DENIED;
case 404 -> PAGE_NOT_FOUND;
case 405 -> METHOD_NOT_ALLOWED;
case 409 -> CONFLICT;
case 413 -> PAYLOAD_TOO_LARGE;
case 429 -> TOO_MANY_REQUESTS;
case 502 -> BAD_GATEWAY;
case 503 -> SERVICE_UNAVAILABLE;
case 504 -> GATEWAY_TIMEOUT;
default -> INTERNAL_SERVER_ERROR;
};
}
public int getHttpStatus() { return httpStatus; }

View File

@@ -0,0 +1,20 @@
package lib.exceptions;
import lib.constants.ApplicationMessage;
/** Single typed application exception carrying a safe user-facing message. */
public class ApplicationException extends RuntimeException {
private final ApplicationMessage applicationMessage;
public ApplicationException(ApplicationMessage message, String technicalMessage) {
super(technicalMessage);
this.applicationMessage = message;
}
public ApplicationException(ApplicationMessage message, String technicalMessage, Throwable cause) {
super(technicalMessage, cause);
this.applicationMessage = message;
}
public ApplicationMessage getApplicationMessage() { return applicationMessage; }
}

View File

@@ -0,0 +1,12 @@
package lib.models;
/** Consistent API response contract for every migrated workflow. */
public record ApiResponse<T>(boolean success, T data, MessageDetails message) {
public static <T> ApiResponse<T> success(T data, MessageDetails message) {
return new ApiResponse<>(true, data, message);
}
public static <T> ApiResponse<T> failure(MessageDetails message) {
return new ApiResponse<>(false, null, message);
}
}

View File

@@ -0,0 +1,87 @@
package lib.models;
import java.io.Serial;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
import lombok.Getter;
import lombok.Setter;
/** User-editable case initiation data. Identity and audit fields come from UserSession. */
@Getter
@Setter
public class ApplicationDetails implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Integer applicationId;
private Short portfolioId;
private Short bankBranchId;
private String applicationNumber;
private String bankCode;
private String product;
private String loanAmount;
private String customerName;
private String fatherName;
private String applicationType;
private String category;
private String dateOfBirth;
private String contactPerson;
private String mobileNumber;
private String specialInstruction;
private Boolean residenceVerification;
private Boolean residenceTelephoneVerification;
private Boolean officeVerification;
private Boolean officeTelephoneVerification;
private Boolean propertyVerification;
private Boolean referenceVerification;
private Boolean documentVerification;
private Boolean residenceCoApplicant;
private Boolean residenceCoProprietor;
private Boolean officeCoProprietor;
private Boolean sameResidenceAddress;
private Boolean sameOfficeAddress;
private Boolean samePropertyAddress;
private String residenceAddress1;
private String residenceAddress2;
private String residenceAddress3;
private String residenceLandmark;
private Integer residenceColonyId;
private String residenceCity;
private String residencePincode;
private String residencePhone;
private String companyName;
private String officeAddress1;
private String officeAddress2;
private String officeAddress3;
private String officeLandmark;
private Integer officeColonyId;
private String officeCity;
private String officePincode;
private String department;
private String designation;
private String officePhone;
private String extension;
private String propertyAddress1;
private String propertyAddress2;
private String propertyAddress3;
private String propertyLandmark;
private Integer propertyColonyId;
private String propertyCity;
private String propertyPincode;
private String referenceName1;
private String referenceAddress1;
private String referenceContactNumber1;
private String referenceName2;
private String referenceAddress2;
private String referenceContactNumber2;
private Map<String, String> dynamicFields = new LinkedHashMap<>();
private Boolean autoCutOff;
private Integer formMode;
}

View File

@@ -0,0 +1,4 @@
package lib.models;
/** Data returned after saving a loan-verification application. */
public record ApplicationSaveData(String operation, Integer applicationId, String mvCode) {}

View File

@@ -0,0 +1,16 @@
package lib.models;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/** Result row returned by the application-save database operation. */
@Getter
@Setter
@NoArgsConstructor
public class ApplicationSaveResult {
private String operation;
private Integer applicationId;
private String mvCode;
private String internalUuid;
}

View File

@@ -9,11 +9,11 @@ import lombok.Setter;
@Getter
@Setter
public class CasePunching {
private ErrorDetails errorDetails;
private MessageDetails messageDetails;
private Map<String, String> optionsl;
private Map<String, List<Option>> options;
private List<String> visibleSections;
private Integer portfolioId;
private Short portfolioId;
private Integer formMode;
private String userId;
private String dynamicFields;

View File

@@ -0,0 +1,11 @@
package lib.models;
/** Hybrid RSA-OAEP/AES-GCM envelope submitted by the initiation page. */
public record CaseSaveRequest(
String keyId,
String encryptedKey,
String initializationVector,
String encryptedPayload,
String requestId,
String timestamp) {
}

View File

@@ -0,0 +1,15 @@
package lib.models;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/** Existing application details used by the case-initiation duplicate checks. */
public record DuplicateDetailsData(List<Map<String, Object>> records) {
public DuplicateDetailsData {
records = records == null ? List.of() : records.stream()
.map(record -> Collections.unmodifiableMap(new LinkedHashMap<>(record)))
.toList();
}
}

View File

@@ -0,0 +1,19 @@
package lib.models;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
public class EditCaseSummary {
private String documentCaseId;
private String mvCode;
private String fileNumber;
private String customerName;
private String applicationType;
private String product;
private String receivedOn;
private String punchedBy;
private String branchCode;
private Short portfolioId;
}

View File

@@ -0,0 +1,10 @@
package lib.models;
import java.util.List;
/** Localities returned to the case-initiation autocomplete. */
public record LocalityData(List<LocalityOption> localities) {
public LocalityData {
localities = localities == null ? List.of() : List.copyOf(localities);
}
}

View File

@@ -0,0 +1,4 @@
package lib.models;
/** One company-authorized locality autocomplete result. */
public record LocalityOption(Integer id, String location, String pincode, String city) {}

View File

@@ -1,6 +1,6 @@
package lib.models;
import lib.constants.ApplicationError;
import lib.constants.ApplicationMessage;
import java.io.Serial;
import java.io.Serializable;
import java.time.Instant;
@@ -10,37 +10,37 @@ import lombok.Getter;
/** Dependency-free error information shared across Cygnus modules. */
@Getter
public final class ErrorDetails implements Serializable {
public final class MessageDetails implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private final int httpStatus;
private final String errorCode;
private final String code;
private final String title;
private final String message;
private final String description;
private final String referenceId;
private final Instant timestamp;
public ErrorDetails(ApplicationError error) {
this(error.getHttpStatus(), error.getCode(), error.getTitle(),
error.getMessage(), error.getDescription(),
public MessageDetails(ApplicationMessage message) {
this(message.getHttpStatus(), message.getCode(), message.getTitle(),
message.getMessage(), message.getDescription(),
UUID.randomUUID().toString(), Instant.now());
}
private ErrorDetails(
private MessageDetails(
int httpStatus,
String errorCode,
String code,
String title,
String message,
String description,
String referenceId,
Instant timestamp) {
if (httpStatus < 400 || httpStatus > 599) {
throw new IllegalArgumentException("HTTP error status must be between 400 and 599");
if (httpStatus < 100 || httpStatus > 599) {
throw new IllegalArgumentException("HTTP status must be between 100 and 599");
}
this.httpStatus = httpStatus;
this.errorCode = required(errorCode, "errorCode");
this.code = required(code, "code");
this.title = required(title, "title");
this.message = required(message, "message");
this.description = description == null ? "" : description.trim();

View File

@@ -8,5 +8,6 @@ import lombok.Setter;
public class Option {
private Object value;
private String label;
private String description;
private String group;
}

View File

@@ -0,0 +1,15 @@
package lib.models;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Collections;
/** Form-shaped punched applications returned to the case-initiation workspace. */
public record PunchedRecordsData(List<Map<String, Object>> records) {
public PunchedRecordsData {
records = records == null ? List.of() : records.stream()
.map(record -> Collections.unmodifiableMap(new LinkedHashMap<>(record)))
.toList();
}
}

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;
}

View File

@@ -1,22 +0,0 @@
package lib.models;
import lib.constants.ApplicationError;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
class ErrorDetailsTest {
@Test
void createsAReusableErrorContract() {
ErrorDetails details = new ErrorDetails(ApplicationError.ACCESS_DENIED);
assertEquals(403, details.getHttpStatus());
assertEquals("AUTH-403", details.getErrorCode());
}
@Test
void mapsHttpStatusToCanonicalError() {
assertEquals(ApplicationError.PAGE_NOT_FOUND, ApplicationError.fromHttpStatus(404));
assertEquals(ApplicationError.INTERNAL_SERVER_ERROR,
ApplicationError.fromHttpStatus(599));
}
}

View File

@@ -0,0 +1,22 @@
package lib.models;
import lib.constants.ApplicationMessage;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
class MessageDetailsTest {
@Test
void createsAReusableErrorContract() {
MessageDetails details = new MessageDetails(ApplicationMessage.ACCESS_DENIED);
assertEquals(403, details.getHttpStatus());
assertEquals("AUTH-403", details.getCode());
}
@Test
void mapsHttpStatusToCanonicalError() {
assertEquals(ApplicationMessage.PAGE_NOT_FOUND, ApplicationMessage.fromHttpStatus(404));
assertEquals(ApplicationMessage.INTERNAL_SERVER_ERROR,
ApplicationMessage.fromHttpStatus(599));
}
}

View File

@@ -1,3 +0,0 @@
artifactId=cygnus-lib
groupId=com.cygnus
version=1.0.0-SNAPSHOT

View File

@@ -1,3 +0,0 @@
lib/models/ErrorDetails.class
lib/models/CasePunching.class
lib/constants/ApplicationError.class

View File

@@ -1,4 +0,0 @@
/Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/main/java/lib/constants/ApplicationError.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/Option.java

View File

@@ -1 +0,0 @@
/Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/test/java/lib/models/ErrorDetailsTest.java

View File

@@ -1,64 +0,0 @@
<?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">
<properties>
<property name="java.specification.version" value="25"/>
<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.vm.vendor" value="Homebrew"/>
<property name="sun.arch.data.model" value="64"/>
<property name="java.vendor.url" value="https://github.com/Homebrew/homebrew-core/issues"/>
<property name="os.name" value="Mac OS X"/>
<property name="java.vm.specification.version" value="25"/>
<property name="sun.java.launcher" value="SUN_STANDARD"/>
<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.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="http.nonProxyHosts" value="local|*.local|169.254/16|*.169.254/16"/>
<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="sun.cpu.endian" value="little"/>
<property name="user.home" value="/Users/maddy"/>
<property name="user.language" value="en"/>
<property name="java.specification.vendor" value="Oracle Corporation"/>
<property name="java.version.date" value="2026-01-20"/>
<property name="java.home" value="/opt/homebrew/Cellar/openjdk/25.0.2/libexec/openjdk.jdk/Contents/Home"/>
<property name="file.separator" value="/"/>
<property name="basedir" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib"/>
<property name="java.vm.compressedOopsMode" value="Zero based"/>
<property name="line.separator" value="&#10;"/>
<property name="java.vm.specification.vendor" value="Oracle Corporation"/>
<property name="java.specification.name" value="Java Platform API Specification"/>
<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="sun.management.compiler" value="HotSpot 64-Bit Tiered Compilers"/>
<property name="ftp.nonProxyHosts" value="local|*.local|169.254/16|*.169.254/16"/>
<property name="java.runtime.version" value="25.0.2"/>
<property name="user.name" value="maddy"/>
<property name="stdout.encoding" value="UTF-8"/>
<property name="path.separator" value=":"/>
<property name="os.version" value="26.5.2"/>
<property name="java.runtime.name" value="OpenJDK Runtime Environment"/>
<property name="file.encoding" value="UTF-8"/>
<property name="java.vm.name" value="OpenJDK 64-Bit Server VM"/>
<property name="java.vendor.version" value="Homebrew"/>
<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.io.tmpdir" value="/var/folders/1l/36214rdn79755j30lcnmgsqh0000gn/T/"/>
<property name="java.version" value="25.0.2"/>
<property name="user.dir" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib"/>
<property name="os.arch" value="aarch64"/>
<property name="java.vm.specification.name" value="Java Virtual Machine Specification"/>
<property name="native.encoding" value="UTF-8"/>
<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="stderr.encoding" value="UTF-8"/>
<property name="java.vendor" value="Homebrew"/>
<property name="java.vm.version" value="25.0.2"/>
<property name="stdin.encoding" value="UTF-8"/>
<property name="sun.io.unicode.encoding" value="UnicodeBig"/>
<property name="socksNonProxyHosts" value="local|*.local|169.254/16|*.169.254/16"/>
<property name="java.class.version" value="69.0"/>
</properties>
<testcase name="mapsHttpStatusToCanonicalError" classname="lib.models.ErrorDetailsTest" time="0.008"/>
<testcase name="createsAReusableErrorContract" classname="lib.models.ErrorDetailsTest" time="0.007"/>
</testsuite>

View File

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

View File

@@ -1,686 +0,0 @@
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@page language="java" session="true" %>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Cygnus 1.0 |
<c:if test="${caseDetails.getFormMode() eq 1}">Add Cases</c:if>
<c:if test="${caseDetails.getFormMode() eq 2}">Edit Details</c:if>
</title>
<script language="javascript" src="/matrix/js/lib/constants.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/jquery1.7.2.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ui/uifuncs.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/lib/jsfuncs.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ui/msgdialog.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ui/select.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/appjs/punching.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/validator.js?ver=2" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ajax.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ajax-dynamic-list.js" type="text/javascript"></script>
<link href="/matrix/css/button.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/div.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/textbox.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/select.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/table.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/autocomplete.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-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/punch-workspace-v3.css?v=1" rel="stylesheet" type="text/css" />
<link href="/matrix/css/add-cases-v4.css?v=5" rel="stylesheet" type="text/css" />
<script src="/matrix/js/matrix-dialog-child.js" type="text/javascript"></script>
<script src="/matrix/js/bootstrap-5.3.8.bundle.min.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" />
<script src="/matrix/js/matrix-frame-dialog.js?v=2" defer></script>
<script src="/matrix/js/matrix-dialog-child.js" type="text/javascript"></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" />
</head>
<body class="matrix-v2 matrix-shell matrix-tool-workspace matrix-punch-workspace matrix-add-cases">
<div id='PageFrame'>
<c:if test="${caseDetails.getFormMode() eq 1}">
<%@ include file="/WEB-INF/app/fragments/app-shell-header.jspf" %>
<%-- Shared shell owns ${Sessvals.menuHtml}. --%>
</c:if>
<div id="formcontainer" class="matrix-tool-workspace__content">
<form:form method="post" name="caseDetails" id="caseDetails" modelAttribute="caseDetails" >
<!-- Common Details (Section1) Visible for all portfolios-->
<div>
<!-- Title -->
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/commondet.png" align="absmiddle" />
<span class="matrix-title-text" align="absmiddle">Common Details</span>
<c:choose>
<c:when test="${caseDetails.getFormMode() eq 1}">
<div class="divselect" id="divportfolio" style="width:167px;position:absolute;top:3px;right:13px;">
<form:select path="PortfolioId" multiple="false" id="portlist" style="width:185px" onchange="SubmitForm('casedet','_parent','caseDetails')">
<form:option value="-1" label="SELECT PORTFOLIO" selected="true"/>
<c:forEach items="${portlist}" var="port">
<form:option value="${port[0]}" label="${port[1]}" />
</c:forEach>
</form:select>
</div>
</c:when>
<c:otherwise>
<form:hidden path="PortfolioId" id="portlist" />
</c:otherwise>
</c:choose>
</div>
<!-- -->
<!-- Form (Section1) -->
<div id="FormPanel1" class="FormPanel">
<table align="center" class="matrix-form-controls" width="99%">
<tr>
<td>
<div class="widget">
<div class="lblcontainer">
MV Code
</div>
<div class="inputcontainer">
<form:input style="width:65px;text-transform:uppercase" readonly="true" path="MvCode" value="${caseDeails.getMvCode()}" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Appl No.
</div>
<div class="inputcontainer">
<form:input maxlength="25" style="width:115px;text-transform:uppercase" id="ApplNo" path="ApplNo" value="${caseDetails.getApplNo()}" onblur="if(validate(this,'t','AlphaNumeric')){FindSameDet(this,'A','CustomerName');}" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Bank Code
</div>
<div class="inputcontainer">
<form:input maxlength="25" style="width:70px;text-transform:uppercase" path="BankCode" value="${caseDetails.getBankCode()}" onblur="validate(this,'f','AlphaNumeric');" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Branch
</div>
<div class="inputcontainer">
<div class="divselect" id="divbranch" style="width:135px;">
<form:select path="BankBranchId" multiple="false" id="branchlist" style="width:153px" onblur="validate(this,'t','');">
<form:option value="-1" label="SELECT" selected="true"/>
<c:forEach items="${branchlist}" var="brnch">
<form:option value="${brnch[0]}" label="${brnch[1]}" />
</c:forEach>
</form:select>
</div>
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Product
</div>
<div class="inputcontainer">
<div class="divselect" id="divproduct" style="width:132px;">
<form:select path="Product" multiple="false" id="prodlist" style="width:150px" onblur="validate(this,'t','');">
<form:option value="-1" label="SELECT" selected="true"/>
<c:forEach items="${prodlist}" var="prod">
<form:option value="${prod[0]}" label="${prod[1]}" />
</c:forEach>
</form:select>
</div>
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Name
</div>
<div class="inputcontainer">
<form:input maxlength="60" style="width:200px" path="CustomerName" value="${caseDetails.getCustomerName()}" onblur="validate(this,'t','AlphaSpace');" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Father Name
</div>
<div class="inputcontainer">
<form:input maxlength="25" style="width:145px" path="FatherName" value="${caseDetails.getFatherName()}" onblur="validate(this,'f','AlphaSpace');" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
App Type
</div>
<div class="inputcontainer">
<div class="divselect" id="divapptype" style="width:135px;">
<form:select path="CustomerType" multiple="false" id="typelist" style="width:153px" onchange="ToggleChks((this.value.toUpperCase()!='APPLICANT' && this.value.toUpperCase()!='-1'),'chksresi!C0L!chksoff!C0L!chksprop!C0L!','!C0L!')" onblur="validate(this,'t','');">
<form:option value="-1" label="SELECT" selected="true"/>
<c:forEach items="${typelist}" var="type">
<form:option value="${type[0]}" label="${type[1]}" />
</c:forEach>
</form:select>
</div>
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Category
</div>
<div class="inputcontainer">
<div class="divselect" id="divcategory" style="width:115px;">
<form:select path="Category" multiple="false" id="catlist" style="width:133px">
<form:option value="-1" label="SELECT" selected="true"/>
<c:forEach items="${catlist}" var="cat">
<form:option value="${cat[0]}" label="${cat[1]}" />
</c:forEach>
</form:select>
</div>
</div>
</div>
<div class="widget">
<div class="lblcontainer">
DOB
</div>
<div class="inputcontainer">
<form:input maxlength="10" style="width:80px" path="DOB" id="dob" value="${caseDetails.getDOB()}" onkeydown="return addSlashes(this,event)" onblur="validate(this,'f','Date')" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Mobile No.
</div>
<div class="inputcontainer">
<form:input maxlength="21" style="width:120px" path="MobileNo" value="${caseDetails.getMobileNo()}" onblur="validate(this,'f','AllowWrong');" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Loan Amt
</div>
<div class="inputcontainer">
<form:input maxlength="15" style="width:100px" path="LoanAmount" value="${caseDetails.getLoanAmount()}" onblur="validate(this,'f','LoanAmount');" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
C Person
</div>
<div class="inputcontainer">
<form:input maxlength="25" style="width:200px" path="ContactPerson" value="${caseDetails.getContactPerson()}" onblur="validate(this,'f','AlphaSpace');" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Special Inst.
</div>
<div class="inputcontainer">
<form:input maxlength="50" id="splist" style="width:833px" path="SpecialInst" value="${caseDetails.getSpecialInst()}" onblur="validate(this,'f','SplInstruction')" />
</div>
</div>
</td>
</tr>
</table>
</div>
<!-- -->
</div>
<!-- -->
<!-- Residence Details (Section2) Visible for portfolios in which residence visit/ residence TVR could be initiated-->
<div id="section2">
<!-- Title -->
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/resdet.png" />
<span class="matrix-title-text">Residence Details</span>
<div class="divchk" id="ctrldiv">
<form:checkbox path="Rvr" id="chkresi" onclick="HandleClick(this)" />RVR&nbsp;
<form:checkbox path="SameResi" id="chksresi" onclick="return FindSameDet(this,'R','ResiPhone')" /><span id="chksresi">Same Resi</span>
<form:checkbox path="Rtvr" id="chkteler" onclick="HandleClick(this)" /><span id="chkteler">RTV</span>
</div>
</div>
<!-- -->
<!-- Form (Section2) -->
<div id="FormPanel2" class="FormPanel">
<table align="center" class="matrix-form-controls" style="width:100%">
<tr>
<td>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
House No.
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="20" style="width:70px" path="ResiAdd1" value="${caseDetails.getResiAdd1()}" onblur="validate(this,document.getElementById('chkresi').checked ? 't':'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Sub Locality
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="70" style="width:180px" path="ResiAdd2" value="${caseDetails.getResiAdd2()}" onblur="validate(this,'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
City
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<div class="divselect" id="divrcity" style="width:110px;">
<form:select path="ResiCity" multiple="false" id="ResiAdd3_citylist" style="width:128px" onblur="validate(this,document.getElementById('chkresi').checked ? 't':'f','')" >
<form:option value="-1" label="Select" selected="true"/>
<form:option value="Unknown" label="Unknown"/>
<c:forEach items="${citylist}" var="city">
<form:option value="${city[0]}" label="${city[1]}" />
</c:forEach>
</form:select>
</div>
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Locality
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="50" style="width:180px" path="ResiAdd3" value="${caseDetails.getResiAdd3()}" onkeyup="ajax_showOptions(this,event)" onblur="onLocalityBlur(this,document.getElementById('chkresi').checked ? 't':'f')" />
<form:hidden path="ResiLoc" id="ResiAdd3_hidden" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Landmark
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="50" style="width:150px" path="ResiLandmark" value="${caseDetails.getResiLandmark()}" onblur="validate(this,'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Pincode
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="6" style="width:45px" id="ResiAdd3_Pincode" path="ResiPincode" value="${caseDetails.getResiPincode()}" onblur="validate(this,document.getElementById('chkresi').checked ? 't':'f','Pincode')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Phone No.
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input maxlength="25" style="width:107px" path="ResiPhone" value="${caseDetails.getResiPhone()}" onblur="validate(this,document.getElementById('chkteler').checked ? 't':'f','Phone')" />
</div>
</div>
</td>
</tr>
</table>
</div>
<!-- -->
</div>
<!-- -->
<!-- Office Details (Section3) Visible for portfolios in which office visit/ office TVR could be initiated-->
<div id="section3">
<!-- Title -->
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/optmale.png" />
<span class="matrix-title-text">Office Details</span>
<div class="divchk" id="ctrldiv">
<form:checkbox path="Ovr" id="chkoffice" onclick="HandleClick(this)" />OVR&nbsp;
<form:checkbox path="RCO" id="chkrco" style="display:none" onclick="HandleClick(this)" /><span id="chkrco">RCO</span>&nbsp;
<form:checkbox path="SameOffice" id="chksoff" onclick="return FindSameDet(this,'O','OffPhone')" /><span id="chksoff">Same Office</span>
<form:checkbox path="Otvr" id="chkteleo" onclick="HandleClick(this)" /><span id="chkteleo">OTV</span>
</div>
</div>
<!-- -->
<!-- Form (Section3) -->
<div id="FormPanel3" class="FormPanel">
<table align="center" class="matrix-form-controls">
<tr>
<td>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Company
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input maxlength="50" style="width:215px" path="CompanyName" value="${caseDetails.getCompanyName()}" onblur="validate(this,'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Plot No.
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="20" style="width:90px" path="OffAdd1" value="${caseDetails.getOffAdd1()}" onblur="validate(this,document.getElementById('chkoffice').checked ? 't':'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Sub Locality
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="70" style="width:200px" path="OffAdd2" value="${caseDetails.getOffAdd2()}" onblur="validate(this,'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
City
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<div class="divselect" id="divocity" style="width:110px;">
<form:select path="OffCity" multiple="false" id="OffAdd3_citylist" style="width:128px" onblur="validate(this,document.getElementById('chkoffice').checked ? 't':'f','')">
<form:option value="-1" label="Select" selected="true"/>
<form:option value="Unknown" label="Unknown"/>
<c:forEach items="${citylist}" var="city">
<form:option value="${city[0]}" label="${city[1]}" />
</c:forEach>
</form:select>
</div>
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Locality
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="50" style="width:200px" path="OffAdd3" value="${caseDetails.getOffAdd3()}" onkeyup="ajax_showOptions(this,event)" onblur="validate(this,document.getElementById('chkoffice').checked ? 't':'f','SplInstruction')" />
<form:hidden path="OffLoc" id="OffAdd3_hidden" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Pincode
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="6" style="width:45px" id="OffAdd3_Pincode" path="OffPincode" value="${caseDetails.getOffPincode()}" onblur="validate(this,document.getElementById('chkoffice').checked ? 't':'f','Pincode')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Landmark
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input maxlength="50" style="width:215px" path="OffLandmark" value="${caseDetails.getOffLandmark()}" onblur="validate(this,'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Department
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input maxlength="25" style="width:200px" path="Department" value="${caseDetails.getDepartment()}" onblur="validate(this,'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Designation
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input maxlength="25" style="width:210px" path="Designation" value="${caseDetails.getDesignation()}" onblur="validate(this,'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Office Phone-Extn
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input maxlength="25" style="width:150px" path="OffPhone" value="${caseDetails.getOffPhone()}" onblur="validate(this,document.getElementById('chkteleo').checked ? 't':'f','Phone')" />-<form:input type="text" style="width:23px" path="Extension" value="${caseDetails.getExtension()}" onblur="validate(this,'f','Extension')" />
</div>
</div>
</td>
</tr>
</table>
</div>
<!-- -->
</div>
<!-- -->
<!-- Property Details (Section4) Visible for portfolios in which property visit could be initiated-->
<div id="section4">
<!-- Title -->
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/resdet.png" />
<span class="matrix-title-text">Property Details</span>
<div class="divchk" id="ctrldiv">
<form:checkbox path="Pvr" id="chkprop" onclick="HandleClick(this)" />PVR&nbsp;
<form:checkbox path="RCP" id="chkrcp" style="display:none" onclick="HandleClick(this)" /><span id="chkrcp">RCP</span>&nbsp;
<form:checkbox path="OCP" id="chkocp" style="display:none" onclick="HandleClick(this)" /><span id="chkocp">OCP</span>&nbsp;
<form:checkbox path="SameProp" id="chksprop" onclick="return FindSameDet(this,'P','PropAdd3_Pincode')" /><span id="chksprop">Same Property</span>
</div>
</div>
<!-- -->
<!-- Form (Section4) -->
<div id="FormPanel4" class="FormPanel">
<table align="center" class="matrix-form-controls">
<tr>
<td>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
House / Plot No.
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="20" style="width:120px" path="PropAdd1" value="${caseDetails.getPropAdd1()}" onblur="validate(this,document.getElementById('chkprop').checked ? 't':'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Sub Locality
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="70" style="width:200px" path="PropAdd2" value="${caseDetails.getPropAdd2()}" onblur="validate(this,'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
City
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<div class="divselect" id="divpcity" style="width:110px;">
<form:select path="PropCity" multiple="false" id="PropAdd3_citylist" style="width:128px" onblur="validate(this,document.getElementById('chkprop').checked ? 't':'f','')">
<form:option value="-1" label="Select" selected="true"/>
<form:option value="Unknown" label="Unknown"/>
<c:forEach items="${citylist}" var="city">
<form:option value="${city[0]}" label="${city[1]}" />
</c:forEach>
</form:select>
</div>
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Locality
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="50" style="width:200px" path="PropAdd3" value="${caseDetails.getPropAdd3()}" onkeyup="ajax_showOptions(this,event)" onblur="validate(this,document.getElementById('chkprop').checked ? 't':'f','SplInstruction')" />
<form:hidden path="PropLoc" id="PropAdd3_hidden" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Landmark
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="50" style="width:180px" path="PropLandmark" value="${caseDetails.getPropLandmark()}" onblur="validate(this,'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
<div class="lblcontainer" style="padding:1px">
Pincode
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<form:input readonly="true" maxlength="6" style="width:45px" id="PropAdd3_Pincode" path="PropPincode" value="${caseDetails.getResiPincode()}" onblur="validate(this,document.getElementById('chkprop').checked ? 't':'f','Pincode')" />
</div>
</div>
</td>
</tr>
</table>
</div>
<!-- -->
</div>
<!-- -->
<!-- Reference Details (Section5) Visible for portfolios in which reference calling could be initiated-->
<div id="section5">
<!-- Title -->
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/ref.png" />
<span class="matrix-title-text">Reference Details</span>
<div class="divchk" id="ctrldiv">
<form:checkbox path="Refvr" id="chkref" onclick="setFormValidation(this,'FormPanel5','Ref1Name,Ref1Address,Ref1Contactno','t,f,t','AlphaSpace,SplInstruction,Phone',false)" />Ref Check&nbsp;
</div>
</div>
<!-- -->
<!-- Form (Section5) -->
<div id="FormPanel5" class="FormPanel">
<table align="center" class="matrix-form-controls">
<tr>
<td>&nbsp;</td>
<td>Name</td>
<td>Address</td>
<td>Contact Numbers</td>
</tr>
<tr>
<td>Reference 1&nbsp;</td>
<td><form:input maxlength="30" style="width:200px" path="Ref1Name" value="${caseDetails.getRef1Name()}" onblur="validate(this,document.getElementById('chkref').checked ? 't':'f','AlphaSpace')" /></td>
<td><form:input maxlength="100" style="width:450px" path="Ref1Address" value="${caseDetails.getRef1Address()}" onblur="validate(this,'f','SplInstruction')" /></td>
<td><form:input maxlength="25" style="width:160px" path="Ref1Contactno" value="${caseDetails.getRef1Contactno()}" onblur="validate(this,document.getElementById('chkref').checked ? 't':'f','Phone')" /></td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Name</td>
<td>Address</td>
<td>Contact Numbers</td>
</tr>
<tr>
<td>Reference 2&nbsp;</td>
<td><form:input maxlength="30" style="width:200px" path="Ref2Name" value="${caseDetails.getRef2Name()}" onblur="validate(this,'f','AlphaSpace')" /></td>
<td><form:input maxlength="100" style="width:450px" path="Ref2Address" value="${caseDetails.getRef2Address()}" onblur="validate(this,'f','SplInstruction')" /></td>
<td><form:input maxlength="25" style="width:160px" path="Ref2Contactno" value="${caseDetails.getRef2Contactno()}" onblur="validate(this,'f','Phone')" /></td>
</tr>
</table>
</div>
<!-- -->
</div>
<!-- -->
<!-- Dynamic Form (Section6). All controls under this section will be generated dynamically during runtime-->
<div id="section6">
<!-- Title -->
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/edit_form.png" alt="" />
<span class="matrix-title-text">Other Details</span>
</div>
<!-- -->
<div id="FormPanel6" class="FormPanel">
${caseDetails.getDynamicPanel()}
</div>
</div>
<!-- -->
<!-- Document Details (Section7) Visible for portfolios in which document verification could be done-->
<div id="section7">
<!-- Title -->
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/documents.png" />
<span class="matrix-title-text">Document Details</span>
<div class="divchk" id="ctrldiv">
<form:checkbox path="Docvr" id="chkdoc" onclick="hideForm(this.id,'FormPanel7')" />Doc VR&nbsp;
</div>
</div>
<!-- -->
<!-- Form (Section7) -->
<div id="FormPanel7" class="FormPanel">
<table align="center" class="matrix-form-controls">
<tr>
<td>Document</td>
<td>Vendor</td>
<td>Service Provider</td>
<td>Name</td>
<td>Unique No.</td>
</tr>
<tr>
<td>
<div class="divselect" id="divdoclist" style="width:90px;">
<select id="doclist" style="width:108px">
<option value="-1" selected="true">
<c:forEach items="${doclist}" var="doc">
<option value="${doc[0]}" >${doc[1]}</option>
</c:forEach>
</select>
</div>
</td>
<td><input type="text" style="width:150px" value="" id="vendor" /></td>
<td><input type="text" style="width:200px" value="" id="serviceprovider" /></td>
<td><input type="text" style="width:200px" value="" id="name" /></td>
<td><input type="text" style="width:180px" value="" id="uniqueno" /></td>
</tr>
</table>
</div>
<!-- -->
</div>
<form:hidden path="DynamicFields" value="${caseDetails.getDynamicFields()}" />
<form:hidden path="VisibleContents" value="${caseDetails.getVisibleContents()}" />
<form:hidden path="FormMode" />
<form:hidden path="UUID" />
<form:hidden path="CaseId" />
<!-- -->
<input type="hidden" id="invalidfields" value="0" />
<c:if test="${caseDetails.getFormMode() eq 2}">
<input type="button" class="button" name="btncancel" style="margin-left:1px;margin-top:5px;float:right" value="Cancel" id="btncancel" accesskey="C" onclick="MatrixDialog.close(0)" />
</c:if>
<input type="button" class="button" name="btnsave" style="margin-top:5px;float:right" value="Save" id="btnsave" accesskey="S" onclick="return ValidateSubmitForm('caseDetails');" />
</form:form>
</div>
</div>
</body>
<!-- Page Load Javascript -->
<script language="javascript" type="text/javascript">
HideSections('rtv');
HideSections('otv');
HideSections('section');
UnhideSections('${visibleContents}','!C0L!');
hideForm('chkresi','FormPanel2');
hideForm('chkoffice','FormPanel3');
hideForm('chkprop','FormPanel4');
hideForm('chkref','FormPanel5');
hideForm('chkdoc','FormPanel7');
ToggleChks((document.getElementById('chkresi').checked && document.getElementById('chkoffice').checked),'chkrco'+ColDelim,ColDelim);
ToggleChks((document.getElementById('chkresi').checked),'chkrcp'+ColDelim,ColDelim);
ToggleChks((document.getElementById('chkoffice').checked),'chkocp'+ColDelim,ColDelim);
ToggleChks((document.getElementById('typelist').value.toUpperCase()!='APPLICANT' && document.getElementById('typelist').value.toUpperCase()!='-1'),'chksresi!C0L!chksoff!C0L!chksprop!C0L!','!C0L!');
document.getElementById('ApplNo').focus();
</script>
<!-- -->
<!-- Process Message -->
<c:if test="${not empty caseDetails.getErrMsg()}">
<script language="javascript" type="text/javascript"> CallMessage('${caseDetails.getErrMsg()}',3000,200,300); </script>
<c:if test="${caseDetails.isProcessFlag()==true and caseDetails.getFormMode()==2}">
<script language="javascript" type="text/javascript">MatrixDialog.close(1);</script>
</c:if>
</c:if>
<!-- -->
</html>

View File

@@ -13,43 +13,42 @@
<script language="javascript" src="/matrix/js/lib/jsfuncs.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ui/msgdialog.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ui/select.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/appjs/editcases.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/edp/punching/edit-cases.js?ver=1" type="text/javascript"></script>
<link href="/matrix/css/div.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/select.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/table.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/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" />
<link href="/matrix/css/edit-cases-v1.css?v=1" rel="stylesheet" type="text/css" />
<title>Cygnus 1.0 | Edit Cases</title>
<link href="/matrix/css/table.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/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" />
<title>Cygnus 1.0 | Edit Cases</title>
<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/edit-cases-v1.css?v=8" rel="stylesheet" type="text/css" />
</head>
<body class="matrix-shell matrix-v2 matrix-tool-workspace matrix-edit-cases">
<body class="matrix-shell matrix-v2 matrix-tool-workspace matrix-edit-cases">
<div id='PageFrame'>
<!-- Title Bar -->
<%@ include file="/WEB-INF/app/fragments/app-title.jspf" %>
<%@ include file="/WEB-INF/app/fragments/app-title.jspf" %>
<!-- -->
<div id="formcontainer" class="matrix-tool-workspace__content">
<form:form method="post" name="caseGrid" id="caseGrid" modelAttribute="caseGrid" target="_blank">
<div id="formcontainer" class="matrix-tool-workspace__content">
<form:form method="post" name="caseGrid" id="caseGrid" modelAttribute="caseGrid" target="_parent">
<!-- Common Details (Section1) Visible for all portfolios-->
<div>
<!-- Title -->
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/commondet.png" align="absmiddle" />
<span class="matrix-title-text" align="absmiddle">List of Cases</span>
<div class="divselect" id="divportfolio" style="width:167px;position:absolute;top:3px;right:30px;">
<form:select path="PortfolioId" multiple="false" id="portlist" style="width:185px" onchange="SubmitForm('caselist','_parent','caseGrid')">
<form:option value="-1" label="SELECT PORTFOLIO" selected="true"/>
<c:forEach items="${portlist}" var="port">
<form:option value="${port[0]}" label="${port[1]}" />
</c:forEach>
</form:select>
</div>
<img class="matrix-title-action" src="/matrix/images/reload.png" title="Refresh Grid" onclick="SubmitForm('caselist','_parent','caseGrid')"/>
</div>
<img class="matrix-title-icon" src="/matrix/images/commondet.png" align="absmiddle" />
<span class="matrix-title-text" align="absmiddle">List of Cases</span>
<form:select path="PortfolioId" multiple="false" id="portlist" cssClass="matrix-edit-cases__portfolio-select" onchange="SubmitForm('caselist','_parent','caseGrid')">
<form:option value="-1" label="SELECT PORTFOLIO" selected="true"/>
<c:forEach items="${portlist}" var="port">
<form:option value="${port.value}" label="${port.label}" />
</c:forEach>
</form:select>
<button class="matrix-edit-cases__refresh" type="button" title="Refresh Grid" onclick="SubmitForm('caselist','_parent','caseGrid')">
<img src="/matrix/images/reload.png" alt="" />
</button>
</div>
<!-- -->
<div id="TablePanel" class="tableContainer">
<table border="0" cellspacing="0" width="100%" id="casetable">
@@ -69,19 +68,19 @@
</thead>
<tbody class="scrollContent">
<c:forEach items="${caseList}" var="casedet" varStatus="status">
<tr id="row${status.count}" tabindex="0" title="Open this case for editing">
<tr id="row${status.count}" tabindex="0" title="Open this case for editing">
<td>
<input type="hidden" name="row${status.count}uuid" id="row${status.count}uuid" value="${casedet[0]}" />
<input type="hidden" name="row${status.count}portid" id="row${status.count}portid" value="${casedet[9]}" />
<input type="hidden" name="row${status.count}uuid" id="row${status.count}uuid" value="${casedet.documentCaseId}" />
<input type="hidden" name="row${status.count}portid" id="row${status.count}portid" value="${casedet.portfolioId}" />
${status.count}</td>
<td>${casedet[1]}</td>
<td>${casedet[2]}</td>
<td>${casedet[3]}</td>
<td>${casedet[4]}</td>
<td>${casedet[5]}</td>
<td>${casedet[6]}</td>
<td>${casedet[7]}</td>
<td>${casedet[8]}</td>
<td>${casedet.mvCode}</td>
<td>${casedet.fileNumber}</td>
<td>${casedet.customerName}</td>
<td>${casedet.applicationType}</td>
<td>${casedet.product}</td>
<td>${casedet.receivedOn}</td>
<td>${casedet.punchedBy}</td>
<td>${casedet.branchCode}</td>
</tr>
</c:forEach>
</tbody>
@@ -103,4 +102,4 @@
<script language="javascript" type="text/javascript"> CallMessage('${msg}',3000,200,300); </script>
</c:if>
<!-- -->
</html>
</html>

View File

@@ -18,12 +18,16 @@
<script language="javascript" src="/matrix/js/jquery1.7.2.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ui/uifuncs.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/lib/jsfuncs.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/lib/notifications.js?ver=1" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/lib/payload-crypto.js?ver=1" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/lib/form-validation.js?ver=1" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ui/msgdialog.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ui/select.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/appjs/punching.js?ver=6" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/edp/punching/initiation.js?ver=8" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/edp/punching/initiation-validation.js?ver=1" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/edp/punching/application-save.js?ver=2" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/validator.js?ver=2" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ajax.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ajax-dynamic-list.js?ver=1" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ajax-dynamic-list.js?ver=2" type="text/javascript"></script>
<link href="/matrix/css/button.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/div.css" rel="stylesheet" type="text/css" />
@@ -32,11 +36,11 @@
<link href="/matrix/css/table.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/autocomplete.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=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/punch-workspace-v3.css?v=1" rel="stylesheet" type="text/css" />
<link href="/matrix/css/add-cases-v4.css?v=5" rel="stylesheet" type="text/css" />
<link href="/matrix/css/punch-workspace-v3.css?v=2" rel="stylesheet" type="text/css" />
<link href="/matrix/css/add-cases-v4.css?v=6" rel="stylesheet" type="text/css" />
<script src="/matrix/js/bootstrap-5.3.8.bundle.min.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" />
@@ -53,7 +57,7 @@
<c:if test="${pageFormMode!=2}">
<!-- Dynamic Menu -->
<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>
<!-- -->
</c:if>
@@ -72,6 +76,9 @@
<label class="matrix-form-title__check"><input type="checkbox" name="autocut" checked id="autocut" /> Auto Cut-Off</label>
<c:if test="${pageFormMode==2}">
<input type="hidden" id="portfolio_id" name="portfolioId" value="${pagePortfolioId}" />
<button type="button" class="matrix-edit-back" onclick="history.back()" title="Back to case list">
<span aria-hidden="true">&#8592;</span> Back
</button>
</c:if>
<c:if test="${pageFormMode!=2}">
<div class="divselect matrix-form-title__end" id="divportfolio" style="width:297px;">
@@ -79,9 +86,9 @@
<option value="-1" selected >SELECT PORTFOLIO</option>
<c:choose>
<c:when test="${not empty model}">
<c:forEach items="${model.options['portfolio.']}" var="port">
<option value="${port.value}"><c:out value="${port.label}" /></option>
</c:forEach>
<c:forEach items="${model.options['portfolio.']}" var="port">
<option value="${port.value}"><c:out value="${port.label}" /></option>
</c:forEach>
</c:when>
<c:otherwise>
<c:forEach items="${portlist}" var="port">
@@ -112,7 +119,7 @@
Appl No.
</div>
<div class="inputcontainer">
<input type="text" id="applno" name="applno" maxlength="25" style="width:115px;text-transform:uppercase" value="" onblur="if(validate(this,'t','AlphaNumeric')){FindSameDet(this,'A','customername');}" />
<input type="text" id="applno" name="applno" maxlength="25" style="width:115px;text-transform:uppercase" value="" onblur="if(CygnusInitiationValidation.validateField(this)){FindSameDet(this,'A','customername');}" />
</div>
</div>
<div class="widget">
@@ -120,7 +127,7 @@
Bank Code
</div>
<div class="inputcontainer">
<input type="text" maxlength="25" id="bankcode" name="bankcode" style="width:70px;text-transform:uppercase" value="" onblur="validate(this,'f','AlphaNumeric');" />
<input type="text" maxlength="25" id="bankcode" name="bankcode" style="width:70px;text-transform:uppercase" value="" onblur="CygnusInitiationValidation.validateField(this);" />
</div>
</div>
<div class="widget">
@@ -129,13 +136,13 @@
</div>
<div class="inputcontainer">
<div class="divselect" id="divbranch" style="width:135px;">
<select id="bank_branch_id" name="bank_branch_id" style="width:153px" onblur="validate(this,'t','');">
<select id="bank_branch_id" name="bank_branch_id" style="width:153px" onblur="CygnusInitiationValidation.validateField(this);">
<option value="-1" selected >SELECT</option>
<c:choose>
<c:when test="${not empty model}">
<c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'branch.')}">
<option value="${fn:substringAfter(option.key, 'branch.')}"><c:out value="${option.value}" /></option>
</c:if></c:forEach>
<c:forEach items="${model.options['branch.']}" var="option">
<option value="${option.value}"><c:out value="${option.label}" /></option>
</c:forEach>
</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:choose>
@@ -149,10 +156,10 @@
</div>
<div class="inputcontainer">
<div class="divselect" id="divproduct" style="width:132px;">
<select id="product" name="product" style="width:150px" onblur="validate(this,'t','');">
<select id="product" name="product" style="width:150px" onblur="CygnusInitiationValidation.validateField(this);">
<option value="-1" selected >SELECT</option>
<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:choose>
</select>
@@ -164,7 +171,7 @@
Name
</div>
<div class="inputcontainer">
<input type="text" id="customername" name="customername" maxlength="100" style="width:200px" value="" onblur="validate(this,'t','AlphaSpace');" />
<input type="text" id="customername" name="customername" maxlength="100" style="width:200px" value="" onblur="CygnusInitiationValidation.validateField(this);" />
</div>
</div>
<div class="widget">
@@ -181,10 +188,10 @@
</div>
<div class="inputcontainer">
<div class="divselect" id="divapptype" style="width:135px;">
<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','soadd','spadd'])" onblur="CygnusInitiationValidation.validateField(this);">
<option value="-1" selected>SELECT</option>
<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:choose>
</select>
@@ -200,7 +207,7 @@
<select id="category" name="category" style="width:133px">
<option value="-1" selected>SELECT</option>
<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:choose>
</select>
@@ -261,10 +268,10 @@
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/resdet.png" />
<span class="matrix-title-text">Residence Details</span>
<div class="divchk" id="ctrldiv">
<input type="checkbox" id="rv" name="rv" onclick="HandleClick(this)" />RVR&nbsp;
<input type="checkbox" id="sradd" name="rv" onclick="return FindSameDet(this,'R','rphone')" /><span id="sradd">Same Resi</span>
<input type="checkbox" id="rtv" name="rv" onclick="HandleClick(this)" /><span id="rtv">RTV</span>
<div class="divchk ctrldiv">
<input type="checkbox" id="rv" name="rv" onclick="HandleClick(this)" />RVR&nbsp;
<input type="checkbox" id="sradd" name="sradd" onclick="return FindSameDet(this,'R','rphone')" /><span id="sradd-label">Same Resi</span>
<input type="checkbox" id="rtv" name="rtv" onclick="HandleClick(this)" /><span id="rtv-label">RTV</span>
</div>
</div>
<!-- -->
@@ -311,7 +318,7 @@
<option value="-1">Select</option>
<option value="Unknown">Unknown</option>
<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:choose>
</select>
@@ -369,11 +376,11 @@
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/optmale.png" />
<span class="matrix-title-text">Office Details</span>
<div class="divchk" id="ctrldiv">
<input type="checkbox" id="ov" onclick="HandleClick(this)" />OVR&nbsp;
<input type="checkbox" id="rco" style="display:none" onclick="HandleClick(this)" /><span id="rco">RCO&nbsp;</span>
<input type="checkbox" id="soadd" onclick="return FindSameDet(this,'O','ophone')" /><span id="soadd">Same Office</span>
<input type="checkbox" id="otv" onclick="HandleClick(this)" /><span id="otv">OTV</span>
<div class="divchk ctrldiv">
<input type="checkbox" id="ov" onclick="HandleClick(this)" />OVR&nbsp;
<input type="checkbox" id="rco" style="display:none" onclick="HandleClick(this)" /><span id="rco-label">RCO&nbsp;</span>
<input type="checkbox" id="soadd" onclick="return FindSameDet(this,'O','ophone')" /><span id="soadd-label">Same Office</span>
<input type="checkbox" id="otv" onclick="HandleClick(this)" /><span id="otv-label">OTV</span>
</div>
</div>
<!-- -->
@@ -429,7 +436,7 @@
<option value="-1">Select</option>
<option value="Unknown">Unknown</option>
<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:choose>
</select>
@@ -470,7 +477,7 @@
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<input type="text" id="department" name="designation" maxlength="50" style="width:100px" value="" onblur="validate(this,'f','SplInstruction')" />
<input type="text" id="department" name="department" maxlength="50" style="width:100px" value="" onblur="validate(this,'f','SplInstruction')" />
</div>
</div>
<div class="widget" style="margin-left:2px">
@@ -487,8 +494,10 @@
Office Phone-Extn
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<input type="text" id="ophone" name="ophone" maxlength="25" style="width:100px" value="" onblur="validate(this,document.getElementById('otv').checked ? 't':'f','Phone')" />-<input type="text" id="extension" name="extension" style="width:23px" maxlength="10" value="" onblur="validate(this,'f','Extension')" />
<div class="inputcontainer matrix-phone-extension" style="padding:1px">
<input type="text" id="ophone" name="ophone" maxlength="25" value="" onblur="validate(this,document.getElementById('otv').checked ? 't':'f','Phone')" />
<span aria-hidden="true">-</span>
<input type="text" id="extension" name="extension" maxlength="10" value="" aria-label="Office phone extension" onblur="validate(this,'f','Extension')" />
</div>
</div>
</td>
@@ -505,11 +514,11 @@
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/resdet.png" />
<span class="matrix-title-text">Property Details</span>
<div class="divchk" id="ctrldiv">
<div class="divchk ctrldiv">
<input type="checkbox" id="pv" onclick="HandleClick(this)" />PVR&nbsp;
<input type="checkbox" id="rcp" style="display:none" onclick="HandleClick(this)" /><span id="rcp">RCP&nbsp;</span>
<input type="checkbox" id="ocp" style="display:none" onclick="HandleClick(this)" /><span id="ocp">OCP&nbsp;</span>
<input type="checkbox" id="spadd" onclick="return FindSameDet(this,'P','ppincode')" /><span id="spadd">Same Property</span>
<input type="checkbox" id="rcp" style="display:none" onclick="HandleClick(this)" /><span id="rcp-label">RCP&nbsp;</span>
<input type="checkbox" id="ocp" style="display:none" onclick="HandleClick(this)" /><span id="ocp-label">OCP&nbsp;</span>
<input type="checkbox" id="spadd" onclick="return FindSameDet(this,'P','ppincode')" /><span id="spadd-label">Same Property</span>
</div>
</div>
<!-- -->
@@ -524,7 +533,7 @@
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<input type="text" id="paddr1" name="paddr1" readonly="readonly" maxlength="40" style="width:90px" value="" onblur="validate(this,document.getElementById('rv').checked ? 't':'f','SplInstruction')" />
<input type="text" id="paddr1" name="paddr1" readonly="readonly" maxlength="40" style="width:90px" value="" onblur="CygnusInitiationValidation.validateField(this);" />
</div>
</div>
<div class="widget" style="margin-left:2px">
@@ -556,7 +565,7 @@
<option value="-1">Select</option>
<option value="Unknown">Unknown</option>
<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:choose>
</select>
@@ -579,7 +588,7 @@
</div>
<br >
<div class="inputcontainer" style="padding:1px">
<input type="text" id="ppincode" name="colp_pincode" readonly="readonly" maxlength="6" style="width:45px" value="" onblur="validate(this,document.getElementById('rv').checked ? 't':'f','Pincode')" />
<input type="text" id="ppincode" name="colp_pincode" readonly="readonly" maxlength="6" style="width:45px" value="" onblur="CygnusInitiationValidation.validateField(this);" />
</div>
</div>
<div class="widget" style="margin-left:2px">
@@ -605,7 +614,7 @@
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/ref.png" />
<span class="matrix-title-text">Reference Details</span>
<div class="divchk" id="ctrldiv">
<div class="divchk ctrldiv">
<input type="checkbox" id="refv" name="refv" onclick="HandleClick(this)" />Ref Check&nbsp;
</div>
</div>
@@ -670,7 +679,7 @@
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/documents.png" />
<span class="matrix-title-text">Document Details</span>
<div class="divchk" id="ctrldiv">
<div class="divchk ctrldiv">
<input type="checkbox" name="docv" id="docv" />Doc VR&nbsp;
</div>
</div>
@@ -689,19 +698,17 @@
</c:if>
<input type="hidden" id="uuid" name="uuid" value="${pageDocumentCaseId}" />
<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="branch_id" name="branch_id" value="${Sessvals.getBranchID()}" />
<input type="hidden" id="company_id" name="company_id" value="${sessionScope.userSession.companyId}" />
<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="invalidfields" value="0" />
<c:if test="${pageFormMode gt 0}">
<div style="position:fixed;text-align:right;bottom:0px;width:980px;" class="buttonbar">
<input type="hidden" id="invalidfields" value="0" />
<input type="button" class="button" name="btnfirst" style="margin-left:5px;margin-top:-2px;float:left;width:80px" value="" id="btnfirst" accesskey="F" onclick="findRecord(1)" />
<input type="button" class="button" name="btnprev" style="margin-top:-2px;float:left;width:80px" value="" id="btnprev" accesskey="P" onclick="findRecord(2)" />
<input type="button" class="button" name="btnnext" style="margin-top:-2px;float:left;width:80px" value="" id="btnnext" accesskey="N" onclick="findRecord(3)" />
<input type="button" class="button" name="btnlast" style="margin-top:-2px;float:left;width:80px" value="" id="btnlast" accesskey="L" onclick="findRecord(4)" />
<input type="button" class="button" name="btnsave" style="float:right" value="Save" id="btnsave" accesskey="S" onclick="return ValidateSubmitForm('casedetails');" />
<input type="button" class="button" name="btnsave" style="float:right" value="Save" id="btnsave" accesskey="S" onclick="return CygnusInitiation.save(event);" />
<c:if test="${pageFormMode!=2}">
<input type="button" class="button" name="btnadd" style="float:right" value="Add" id="btnadd" accesskey="A" onclick="return AddNewRecord();" />
</c:if>
@@ -710,9 +717,9 @@
</form>
<input type="hidden" id="formmode" name="formmode" value="${pageFormMode}" />
<input type="hidden" id="usid" name="usid" value="${pageUserId}" />
<c:if test="${not empty model.errorDetails}">
<span id="page-error-code" hidden><c:out value="${model.errorDetails.errorCode}" /></span>
<span id="page-error-message" hidden><c:out value="${model.errorDetails.message}" /></span>
<c:if test="${not empty model.messageDetails}">
<span id="page-error-code" hidden><c:out value="${model.messageDetails.code}" /></span>
<span id="page-error-message" hidden><c:out value="${model.messageDetails.message}" /></span>
</c:if>
</div>
</div>
@@ -720,6 +727,7 @@
<!-- Page Load Javascript -->
<script language="javascript" type="text/javascript">
(function () {
CygnusInitiationValidation.bind(document.getElementById("casedetails"));
var sectionFields = document.querySelectorAll(".model-visible-section");
if (sectionFields.length > 0) {
document.getElementById("visiblecontents").value = Array.prototype.map.call(
@@ -728,10 +736,13 @@
}
InitPage();
var errorCode = document.getElementById("page-error-code");
var code = document.getElementById("page-error-code");
var errorMessage = document.getElementById("page-error-message");
if (errorCode && errorMessage) {
CallMessage(errorCode.textContent + ":error:" + errorMessage.textContent, 3000, 200, 300);
if (code && errorMessage) {
CygnusNotifications.show({
type: "danger", code: code.textContent,
message: errorMessage.textContent, duration: 3000
});
}
}());
</script>

View File

@@ -1,329 +0,0 @@
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@page language="java" session="true" %>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Cygnus 1.0 | Document Initiation </title>
<script language="javascript" src="/matrix/js/lib/constants.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/jquery1.7.2.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ui/uifuncs.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/lib/jsfuncs.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ui/msgdialog.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ui/select.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ajax.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/ajax-dynamic-list.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/appjs/punchingdoc.js" type="text/javascript"></script>
<script language="javascript" src="/matrix/js/validator.js?ver=2" type="text/javascript"></script>
<link href="/matrix/css/button.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/div.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/textbox.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/select.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/table.css" rel="stylesheet" type="text/css" />
<link href="/matrix/css/autocomplete.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-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/punch-workspace-v3.css?v=1" rel="stylesheet" type="text/css" />
<link href="/matrix/css/add-cases-v4.css?v=5" rel="stylesheet" type="text/css" />
<script src="/matrix/js/bootstrap-5.3.8.bundle.min.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" />
<script src="/matrix/js/matrix-frame-dialog.js?v=2" 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" />
</head>
<body class="matrix-v2 matrix-shell matrix-tool-workspace matrix-punch-workspace matrix-add-cases">
<div id='PageFrame'>
<%@ include file="/WEB-INF/app/fragments/app-shell-header.jspf" %>
<%-- Shared shell owns ${Sessvals.menuHtml}. --%>
<div id="formcontainer" class="matrix-tool-workspace__content">
<form method="post" name="docdetails" id="docdetails" >
<!-- Common Details (Section1) Visible for all portfolios-->
<div>
<!-- Title -->
<div class="title matrix-form-title">
<img class="matrix-title-icon" src="/matrix/images/commondet.png" align="absmiddle" />
<span class="matrix-title-text matrix-form-title__heading">Common Details <span id='recfound'></span></span>
<label class="matrix-form-title__field">Skip To <input type="text" class="textbox" style="width:30px" onkeypress="return NumberOnly(event)" onblur="GotoRecord(this)"></label>
<label class="matrix-form-title__field">Search by File No <input type="text" class="textbox" style="width:200px" onblur="SearchRecord(this)"></label>
<!-- Checkbox for AUTO CUT diabled for now -->
<!-- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" name="autocut" id="autocut" />&nbsp;Automatic Cut-Off -->
<div class="divselect matrix-form-title__end" id="divportfolio" style="width:167px;">
<select id="portfolio_id" name="portfolio_id" style="width:185px" onchange="SubmitForm('docadd','_parent','docdetails')">
<option value="-1" selected >SELECT PORTFOLIO</option>
<c:forEach items="${portlist}" var="port">
<option value="${port[0]}">${port[1]}</option>
</c:forEach>
</select>
</div>
</div>
<!-- -->
<!-- Form (Section1) -->
<div id="FormPanel1" class="FormPanel">
<table align="center" class="matrix-form-controls" width="99%">
<tr>
<td>
<div style="height:auto;width:16px;float:right;margin-top:4px;">
<div id="btnbedit" onclick="EditBasicDetails()" title="edit basic details" style="background:url('/matrix/images/edit_form.png');height:auto;width:16px;cursor:pointer;margin-top:2px">&nbsp;</div>
<div id="btnbsave" onclick="SaveBasicDetails()" title="save details" style="background:url('/matrix/images/disk.png');height:auto;width:16px;cursor:pointer;margin-top:2px">&nbsp;</div>
<div id="btnbcancel" onclick="CancelEdit()" title="cancel" style="background:url('/matrix/images/msgerror.png');height:auto;width:16px;cursor:pointer;margin-top:6px">&nbsp;</div>
</div>
<div class="widget">
<div class="lblcontainer">
Appl No.
</div>
<div class="inputcontainer">
<input type="text" id="applno" name="applno" maxlength="25" style="width:150px;text-transform:uppercase" value="" disabled="disabled" onblur="if(validate(this,'t','AlphaNumeric')){FindSameDet(this,'A','customername');}" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Name
</div>
<div class="inputcontainer">
<input type="text" id="customername" name="customername" maxlength="100" style="width:275px" value="" onblur="validate(this,'t','AlphaSpace');" disabled="disabled" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
DOB
</div>
<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')" disabled="disabled" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Loan Amt
</div>
<div class="inputcontainer">
<input type="text" id="loanamount" name="loanamount" maxlength="15" style="width:115px" value="" onblur="validate(this,'f','LoanAmount');" disabled="disabled" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Branch
</div>
<div class="inputcontainer">
<div class="divselect" id="divbranch" style="width:235px;">
<select id="bank_branch_id" name="bank_branch_id" style="width:253px" onblur="validate(this,'t','');" disabled="disabled">
<option value="-1" selected >SELECT</option>
<c:forEach items="${branchlist}" var="brnch">
<option value="${brnch[0]}">${brnch[1]}</option>
</c:forEach>
</select>
</div>
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Product
</div>
<div class="inputcontainer">
<div class="divselect" id="divproduct" style="width:132px;">
<select id="product" name="product" style="width:150px" onblur="validate(this,'t','');" disabled="disabled">
<option value="-1" selected >SELECT</option>
<c:forEach items="${prodlist}" var="prod">
<option value="${prod[0]}">${prod[1]}</option>
</c:forEach>
</select>
</div>
</div>
</div>
<div class="widget">
<div class="lblcontainer">
App Type
</div>
<div class="inputcontainer">
<div class="divselect" id="divapptype" style="width:135px;">
<select id="apptype" name="apptype" style="width:153px" onblur="validate(this,'t','');" disabled="disabled">
<option value="-1" selected>SELECT</option>
<c:forEach items="${typelist}" var="type">
<option value="${type[0]}">${type[1]}</option>
</c:forEach>
</select>
</div>
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Category
</div>
<div class="inputcontainer">
<div class="divselect" id="divcategory" style="width:115px;">
<select id="category" name="category" style="width:133px" disabled="disabled">
<option value="-1" selected>SELECT</option>
<c:forEach items="${catlist}" var="cat">
<option value="${cat[0]}">${cat[1]}</option>
</c:forEach>
</select>
</div>
</div>
</div>
${dynamichtml}
<input type="button" class="button" name="btnsave" style="float:right" value="Add Docs" id="btnsave" onclick="return AddDocs();" />
</td>
</tr>
</table>
</div>
<!-- -->
</div>
<!-- -->
<!-- Document Details Visible for portfolios in which document verification could be done-->
<div id="section7">
<!-- Title -->
<div class="title">
<img class="matrix-title-icon" src="/matrix/images/documents.png" />
<span class="matrix-title-text">Document Details</span>
</div>
<!-- -->
<!-- Form (Section1) -->
<div id="FormPanel1" class="FormPanel">
<table align="center" class="matrix-form-controls" width="99%">
<tr>
<td>
<div class="widget">
<div class="lblcontainer">
Document
</div>
<div class="inputcontainer">
<div class="divselect" id="divdoctype" style="width:170px;">
<select id="doctype" name="doctype" style="width:188px" onchange="changeLabel(this)" onblur="validate(this,'t','')">
<option value="-1" uniqueidentifier="Unique No." sprovider="Service Provider" validuno="xxx" ymon="A.Y/Month" validymon="" defsprovider="" genlist="0" selected>SELECT</option>
<c:forEach items="${doclist}" var="doc">
<option value="${doc[0]}" uniqueidentifier="${doc[2]}" sprovider="${doc[3]}" validuno="${doc[4]}" ymon="${doc[5]}" validymon="${doc[6]}" defsprovider="${doc[7]}" genlist="${doc[8]}">${doc[1]}</option>
</c:forEach>
</select>
</div>
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Name
</div>
<div class="inputcontainer">
<input type="text" id="docholdername" name="docholdername" maxlength="100" style="width:200px" value="" onblur="validate(this,'t','AlphaSpace');" />
</div>
</div>
<div class="widget">
<div class="lblcontainer" id="sprovider">
Serivce Provider
</div>
<div class="inputcontainer">
<input type="text" id="serviceprovider" name="serviceprovider" maxlength="100" style="width:200px" value="" onblur="validate(this,'t','SplInstruction');" />
<input type="hidden" id="bank_id" name="serviceprovider_hidden" value="0" />
<input type="hidden" id="serviceprovider_citylist" name="serviceprovider_citylist" value="0" />
</div>
</div>
<div class="widget">
<div class="lblcontainer" id="uniqueidentifier">
Unique No.
</div>
<div class="inputcontainer">
<input type="text" id="uniqueno" name="uniqueno" maxlength="50" style="width:140px" value="" />
</div>
</div>
<div class="widget">
<div class="lblcontainer" id="yearmon">
A.Y/Month
</div>
<div class="inputcontainer">
<input type="text" id="yearmonth" name="yearmonth" maxlength="100" style="width:180px" value="" />
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Location
</div>
<div class="inputcontainer">
<div class="divselect" id="divcity" style="width:120px;" >
<select id="city" name="city" style="width:138px" onblur="validate(this,'t','');">
<option value="-1" selected>SELECT</option>
<option value="CITY" selected>CITY</option>
<option value="SATELLITE CITY">SATELLITE CITY</option>
<option value="OUT STATION">OUT STATION</option>
</select>
</div>
</div>
</div>
<div class="widget">
<div class="lblcontainer">
Vendor
</div>
<div class="inputcontainer">
<div class="divselect" id="divvendor" style="width:120px;">
<select id="vendor_id" name="vendor_id" style="width:138px" onblur="validate(this,'f','');">
<option value="-1" selected>SELECT</option>
</select>
</div>
</div>
</div>
${docdynamichtml}
<input type="button" class="button" name="btnadd" style="float:right" value="Add" id="btnadd" onclick="return AddNewDoc();" />
</td>
</tr>
</table>
</div>
<div id="FormPanel2" class="FormPanel">
<table border="0" cellspacing="0" width="100%" id="casetable">
<thead class="thead">
<tr title="Row Title" id="rowtitle">
<td style="font-size:12px;width:20px">S.No</td>
<td style="font-size:12px;width:150px">Name</td>
<td style="font-size:12px;width:150px">Document</td>
<td style="font-size:12px;width:150px">Provider</td>
<td style="font-size:12px;width:150px">Unique No.</td>
<td style="font-size:12px;width:100px">Extra</td>
<td style="font-size:12px;width:50px">Location</td>
<td style="font-size:12px;width:50px">Vendor</td>
<td style="font-size:12px">Action</td>
</tr>
</thead>
</table>
</div>
<!-- -->
</div>
<input type="hidden" id="dynamicfields" name="dynamicfields" value="${dynamicfields}" />
<input type="hidden" id="docdynamicfields" name="dynamicfields" value="${docdynamicfields}" />
<input type="hidden" id="uuid" name="uuid" 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="branch_id" name="branch_id" value="${Sessvals.getBranchID()}" />
<input type="hidden" id="status" name="status" value="" />
<input type="hidden" id="docv" name="docv" value="0" />
<!-- -->
<input type="hidden" id="invalidfields" value="0" />
<c:if test="${formmode gt 0}">
<div style="position:fixed;text-align:right;bottom:0px;width:980px;" class="buttonbar">
<input type="hidden" id="invalidfields" value="0" />
<input type="button" class="button" name="btnfirst" style="margin-left:5px;margin-top:-2px;float:left;width:80px" value="" id="btnfirst" accesskey="F" onclick="findRecord(1)" />
<input type="button" class="button" name="btnprev" style="margin-top:-2px;float:left;width:80px" value="" id="btnprev" accesskey="P" onclick="findRecord(2)" />
<input type="button" class="button" name="btnnext" style="margin-top:-2px;float:left;width:80px" value="" id="btnnext" accesskey="N" onclick="findRecord(3)" />
<input type="button" class="button" name="btnlast" style="margin-top:-2px;float:left;width:80px" value="" id="btnlast" accesskey="L" onclick="findRecord(4)" />
<input type="button" class="button" name="btnadd" style="float:right" value="Add New Record" id="btnadd" accesskey="A" onclick="return AddNewRecord();" />
</div>
</c:if>
</form>
<input type="hidden" id="formmode" name="formmode" value="${formmode}" />
<input type="hidden" id="usid" name="usid" value="${usid}" />
</div>
</div>
</body>
<!-- Page Load Javascript -->
<script language="javascript" type="text/javascript">
InitPage('${portfolio_id}');
</script>
<!-- -->
<!-- Process Message -->
<c:if test="${not empty msg}">
<script language="javascript" type="text/javascript"> CallMessage('${msg}',3000,200,300); </script>
</c:if>
<!-- -->
</html>

View File

@@ -10,9 +10,9 @@
<link href="<c:url value='/css/matrix-shell-v2.css' />" rel="stylesheet" />
<link href="<c:url value='/css/matrix-theme-v2.css' />" rel="stylesheet" />
<script src="<c:url value='/js/matrix-shell-v2.js' />" defer></script>
<title>Cygnus 1.0 | <c:out value="${empty errorDetails.title ? 'Page unavailable' : errorDetails.title}" /></title>
<title>Cygnus 1.0 | <c:out value="${empty messageDetails.title ? 'Page unavailable' : messageDetails.title}" /></title>
</head>
<body class="matrix-v2 matrix-shell matrix-error-page matrix-error-page--${empty errorDetails.httpStatus ? 404 : errorDetails.httpStatus}">
<body class="matrix-v2 matrix-shell matrix-error-page matrix-error-page--${empty messageDetails.httpStatus ? 404 : messageDetails.httpStatus}">
<c:choose>
<c:when test="${not empty Sessvals and not empty Sessvals.menuHtml}">
<%@ include file="/WEB-INF/app/fragments/app-shell-header.jspf" %>
@@ -25,20 +25,20 @@
<main class="matrix-error-layout" id="mainContent">
<section class="matrix-error-card" role="alert" aria-labelledby="errorTitle">
<div class="matrix-error-card__status" aria-hidden="true">
<span><c:out value="${empty errorDetails.httpStatus ? 404 : errorDetails.httpStatus}" /></span>
<span><c:out value="${empty messageDetails.httpStatus ? 404 : messageDetails.httpStatus}" /></span>
</div>
<div class="matrix-error-card__content">
<span class="matrix-error-card__eyebrow">
Error <c:out value="${empty errorDetails.errorCode ? 'HTTP-404' : errorDetails.errorCode}" />
Error <c:out value="${empty messageDetails.code ? 'HTTP-404' : messageDetails.code}" />
</span>
<h1 id="errorTitle">
<c:out value="${empty errorDetails.title ? 'Page unavailable' : errorDetails.title}" />
<c:out value="${empty messageDetails.title ? 'Page unavailable' : messageDetails.title}" />
</h1>
<p class="matrix-error-card__message">
<c:out value="${empty errorDetails.message ? 'The requested page is unavailable.' : errorDetails.message}" />
<c:out value="${empty messageDetails.message ? 'The requested page is unavailable.' : messageDetails.message}" />
</p>
<c:if test="${not empty errorDetails.description}">
<p class="matrix-error-card__description"><c:out value="${errorDetails.description}" /></p>
<c:if test="${not empty messageDetails.description}">
<p class="matrix-error-card__description"><c:out value="${messageDetails.description}" /></p>
</c:if>
<div class="matrix-error-card__actions">
@@ -55,9 +55,9 @@
</c:choose>
</div>
<c:if test="${not empty errorDetails.referenceId}">
<c:if test="${not empty messageDetails.referenceId}">
<p class="matrix-error-card__reference">
Reference ID: <code><c:out value="${errorDetails.referenceId}" /></code>
Reference ID: <code><c:out value="${messageDetails.referenceId}" /></code>
</p>
</c:if>
</div>

View File

@@ -6,8 +6,8 @@
<span>Cygnus 1.0</span>
</div>
<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__user"><c:out value="${Sessvals.getUserDisplayName()}" /> (<c:out value="${Sessvals.getUserGroupName()}" />)</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="${sessionScope.userSession.userDisplayName}" /> (<c:out value="${sessionScope.userSession.userGroupName}" />)</span>
</div>
</div>
</header>

View File

@@ -63,6 +63,41 @@
.matrix-add-cases .matrix-form-controls textarea {
width: 100% !important;
min-height: 30px;
font-weight: 400;
}
.matrix-add-cases .matrix-phone-extension {
display: grid;
grid-template-columns: minmax(0, 1fr) auto 48px;
align-items: center;
gap: 4px;
}
.matrix-add-cases .matrix-phone-extension > input {
width: 100% !important;
min-width: 0;
}
.matrix-add-cases .matrix-edit-back {
display: inline-flex;
align-items: center;
gap: 5px;
min-height: 28px;
margin-left: auto;
padding: 3px 10px;
color: #245f91;
font-size: 12px;
font-weight: 600;
border: 1px solid #9eb5c8;
border-radius: 4px;
background: #f6f9fb;
}
.matrix-add-cases .matrix-edit-back:hover,
.matrix-add-cases .matrix-edit-back:focus-visible {
color: #fff;
border-color: #28699d;
background: #28699d;
}
.matrix-add-cases .matrix-form-controls .widget:has(#splist),

View File

@@ -75,7 +75,8 @@
right:8px;
cursor:pointer;
}
.title #ctrldiv
.title #ctrldiv,
.title .ctrldiv
{
border:none;
position:relative;

View File

@@ -4,19 +4,66 @@
background: #f4f8fb;
}
.matrix-edit-cases .matrix-tool-workspace__content > .title .divselect {
width: min(330px, 38vw) !important;
margin-left: auto;
position: static !important;
.matrix-edit-cases #caseGrid > div > .title {
display: flex !important;
align-items: center;
flex-wrap: nowrap !important;
gap: 7px;
}
.matrix-edit-cases .matrix-tool-workspace__content > .title select {
width: 100% !important;
min-height: 28px;
padding: 3px 28px 3px 7px;
border: 1px solid #9fb1c1;
border-radius: 3px;
background-color: #fff;
.matrix-edit-cases #caseGrid > div > .title > .matrix-title-text {
flex: 0 0 auto;
white-space: nowrap;
}
.matrix-edit-cases #caseGrid > div > .title > .matrix-edit-cases__portfolio-select {
width: 0 !important;
min-width: 0;
flex: 1 1 auto;
margin: 0 !important;
font-family: Tahoma, Arial, sans-serif;
font-size: 10pt;
font-weight: 400;
padding: 2px 30px 2px 7px !important;
}
.matrix-edit-cases #caseGrid > div > .title > .matrix-edit-cases__refresh {
box-sizing: border-box !important;
width: 27px !important;
height: 27px !important;
min-width: 27px !important;
min-height: 27px !important;
margin: 0 !important;
flex: 0 0 27px;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0 !important;
border: 0 !important;
border-radius: 0 !important;
outline: 0 !important;
appearance: none;
background: transparent !important;
box-shadow: none !important;
}
.matrix-edit-cases #caseGrid > div > .title > .matrix-edit-cases__refresh:hover,
.matrix-edit-cases #caseGrid > div > .title > .matrix-edit-cases__refresh:focus,
.matrix-edit-cases #caseGrid > div > .title > .matrix-edit-cases__refresh:focus-visible,
.matrix-edit-cases #caseGrid > div > .title > .matrix-edit-cases__refresh:active {
width: 27px !important;
height: 27px !important;
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
outline: 0 !important;
background: transparent !important;
box-shadow: none !important;
}
.matrix-edit-cases .matrix-edit-cases__refresh img {
width: 16px;
height: 16px;
}
.matrix-edit-cases .tableContainer {
@@ -55,12 +102,4 @@
width: 100% !important;
}
.matrix-edit-cases .matrix-tool-workspace__content > .title {
flex-wrap: wrap;
}
.matrix-edit-cases .matrix-tool-workspace__content > .title .divselect {
width: 100% !important;
order: 3;
}
}

View File

@@ -123,6 +123,22 @@ body.matrix-v2 #PageFrame {
border-radius: var(--matrix-radius-sm);
}
.matrix-v2 #cygnus-notifications .alert-dismissible {
position: relative;
padding-right: 38px;
}
.matrix-v2 #cygnus-notifications .alert-dismissible > .btn-close {
position: absolute;
top: 50%;
right: 10px;
width: 1em;
height: 1em;
margin: 0;
padding: 0;
transform: translateY(-50%);
}
/* Shared title treatment for migrated and legacy-backed views. */
.matrix-v2 .title,
.matrix-v2 .card-header,

View File

@@ -53,11 +53,14 @@
min-width: 72px;
}
.matrix-punch-workspace .buttonbar input[id="btnsave"],
.matrix-punch-workspace .buttonbar input[id="btnadd"] {
.matrix-punch-workspace .buttonbar input[id="btnsave"] {
margin-left: auto !important;
}
.matrix-punch-workspace .buttonbar input[id="btnadd"] {
margin-left: 0 !important;
}
.matrix-punch-workspace #formcontainer > .title {
position: sticky;
z-index: 21;

View File

@@ -31,8 +31,7 @@ Owner of DHTMLgoodies.com
var ajax_list_externalFile = 'getlocality'; // Path to external file
var minimumLettersBeforeLookup = 1; // Number of letters entered before a lookup is performed.
var ajax_list_objects = new Array();
var ajax_list_cachedLists = new Array();
var ajax_list_cachedLists = new Array();
var ajax_list_activeInput = false;
var ajax_list_activeItem;
var ajax_list_optionDivFirstItem = false;
@@ -40,7 +39,7 @@ Owner of DHTMLgoodies.com
var ajax_optionDiv = false;
var ajax_optionDiv_iframe = false;
var ajax_list_MSIE = false;
var ajax_list_MSIE = false;
var currentListIndex = 0;
@@ -75,19 +74,13 @@ Owner of DHTMLgoodies.com
ajax_list_activeInput.value = tmpValue;
if(document.getElementsByName(ajax_list_activeInput.name + '_hidden')[0])
{
document.getElementsByName(ajax_list_activeInput.name + '_hidden')[0].value = inputObj.id.split("#-#")[0];
if(ajax_list_externalFile == 'getlocality')
{
document.getElementsByName(ajax_list_activeInput.name + '_pincode')[0].value = inputObj.id.split("#-#")[1];
document.getElementsByName(ajax_list_activeInput.name + '_citylist')[0].value = inputObj.id.split("#-#")[2];
document.getElementsByName(ajax_list_activeInput.name + '_hidden')[0].value = inputObj.dataset.localityId;
if(ajax_list_externalFile == 'getlocality')
{
document.getElementsByName(ajax_list_activeInput.name + '_pincode')[0].value = inputObj.dataset.pincode;
document.getElementsByName(ajax_list_activeInput.name + '_citylist')[0].value = inputObj.dataset.city;
}
//$('#'+ajax_list_activeInput.name + '_pincode').val(inputObj.id.split("#-#")[1]);
//$('#'+ajax_list_activeInput.name + '_citylist').val(inputObj.id.split("#-#")[2]);
}
//var f1=setTimeout('ajax_list_activeInput.focus()',1);
//var f2=setTimeout('ajax_list_activeInput.value = ajax_list_activeInput.value',1);
ajax_options_hide();
}
@@ -119,7 +112,7 @@ Owner of DHTMLgoodies.com
ajax_optionDiv.innerHTML = '';
ajax_list_activeItem = false;
if(ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()].length<=1){
if(ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()].length===0){
ajax_options_hide();
return;
}
@@ -129,19 +122,20 @@ Owner of DHTMLgoodies.com
ajax_list_optionDivFirstItem = false;
var optionsAdded = false;
for(var no=0;no<ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()].length;no++){
if(ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()][no].length==0)continue;
optionsAdded = true;
var div = document.createElement('DIV');
var items = ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()][no].split(/!C0L!/gi);
if(ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()].length==1 && ajax_list_activeInput.value == items[0]){
ajax_options_hide();
return;
}
div.innerHTML = items[items.length-1];
div.id = items[0];
var locality = ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()][no];
if(!locality || !locality.location)continue;
optionsAdded = true;
var div = document.createElement('DIV');
if(ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()].length==1 && ajax_list_activeInput.value == locality.location){
ajax_options_hide();
return;
}
div.textContent = locality.location;
div.dataset.localityId = locality.id;
div.dataset.pincode = locality.pincode || '';
div.dataset.city = locality.city || '';
div.className='optionDiv';
div.onmouseover = function(){ ajax_options_rollOverActiveItem(this,false); };
div.onclick = ajax_option_setValue;
@@ -156,17 +150,6 @@ Owner of DHTMLgoodies.com
}
function ajax_option_list_showContent(ajaxIndex,inputObj,paramToExternalFile,whichIndex)
{
if(whichIndex!=currentListIndex)return;
var letters = inputObj.value;
var content = ajax_list_objects[ajaxIndex].response;
var elements = content.split('!R0W!');
ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()] = elements;
ajax_option_list_buildList(letters,paramToExternalFile);
}
function ajax_option_resize(inputObj)
{
ajax_optionDiv.style.top = (ajax_getTopPos(inputObj) + inputObj.offsetHeight + ajaxBox_offsetY) + 'px';
@@ -250,18 +233,27 @@ Owner of DHTMLgoodies.com
if(ajax_list_cachedLists[paramToExternalFile][inputObj.value.toLowerCase()]){
ajax_option_list_buildList(inputObj.value,paramToExternalFile,currentListIndex);
}else{
var tmpIndex=currentListIndex/1;
ajax_optionDiv.innerHTML = '';
var ajaxIndex = ajax_list_objects.length;
ajax_list_objects[ajaxIndex] = new sack();
if(cityval.toUpperCase() == "GURGAON") {
cityval = "Gurugram";
}
//var url = ajax_list_externalFile + '?' + paramToExternalFile + '='+cityval+'&letters=' + inputObj.value.replace(" ","+");
var url = ajax_list_externalFile + '?city='+cityval+'&letters=' + inputObj.value.replace(" ","+");
ajax_list_objects[ajaxIndex].requestFile = url; // Specifying which file to get
ajax_list_objects[ajaxIndex].onCompletion = function(){ ajax_option_list_showContent(ajaxIndex,inputObj,paramToExternalFile,tmpIndex); }; // Specify function that will be executed after file has been found
ajax_list_objects[ajaxIndex].runAJAX(); // Execute AJAX function
var tmpIndex=currentListIndex/1;
ajax_optionDiv.innerHTML = '';
if(cityval.toUpperCase() == "GURGAON") {
cityval = "Gurugram";
}
var letters=inputObj.value;
var url=ajax_list_externalFile+'?'+new URLSearchParams({city:cityval,letters:letters}).toString();
fetch(url,{method:'GET',credentials:'same-origin',headers:{Accept:'application/json'}})
.then(function(response){return response.json().then(function(body){return {response:response,body:body};});})
.then(function(result){
if(!result.response.ok || !result.body || !result.body.success) throw result.body && result.body.message ? result.body.message : {};
var localities=Array.isArray(result.body.data && result.body.data.localities) ? result.body.data.localities : [];
ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()]=localities;
if(tmpIndex==currentListIndex) ajax_option_list_buildList(letters,paramToExternalFile);
})
.catch(function(error){
if(tmpIndex!=currentListIndex)return;
ajax_options_hide();
CygnusNotifications.show({type:'danger',code:error.code || 'APP-5002',
message:error.message || 'Cygnus could not load localities.',referenceId:error.referenceId});
});
}
@@ -269,7 +261,7 @@ Owner of DHTMLgoodies.com
function ajax_option_keyNavigation(e)
{
if(!ajax_optionDiv)return;
if(!ajax_optionDiv)return;
if(ajax_optionDiv.style.display=='none')return;
if(e.keyCode==38){ // Up arrow
@@ -302,7 +294,7 @@ Owner of DHTMLgoodies.com
function autoHideList(e)
{
var source = e.target;
var source = e.target;
if (source.nodeType == 3) // defeat Safari bug
source = source.parentNode;
if(source.tagName.toLowerCase()!='input' && source.tagName.toLowerCase()!='textarea')
@@ -310,4 +302,4 @@ Owner of DHTMLgoodies.com
document.getElementsByName(ajax_list_activeInput.name + '_hidden')[0].value = '';
ajax_options_hide();
}
}
}

View File

@@ -1,120 +0,0 @@
var currow=null;
function ValidateEntry(flag)
{
validate(document.getElementById("doctype"),flag,'');
validate(document.getElementById("docholdername"),flag,'SplInstruction');
if(validateHidden && $("#serviceprovider_hidden").val()=='')
{
$("#serviceprovider").val('');
}
validate(document.getElementById("serviceprovider"),flag,'SplInstruction');
var temp=$("#uniqueno").attr("onblur").replace( "validate(","" ).replace( ")","").replace(/'/g,"").split(",");
validate(document.getElementById("uniqueno"),flag,temp[2]);
var temp=$("#yearmonth").attr("onblur").replace( "validate(","" ).replace( ")","").replace(/'/g,"").split(",");
validate(document.getElementById("yearmonth"),temp[1],temp[2]);
validate(document.getElementById("city"),flag,'');
}
function AddNewDoc()
{
ValidateEntry('t');
if(checkForm())
{
UpdateDoc();
}
else
{
CallMessage('VLFRM:error:There are one or more error(s) in form. Please correct them and try again.',3000,200,300);
}
}
function AddDocRow(data,did,vname)
{
var tbody = $('#doclist');
var totdocs= $('#doclist tr').length;
var row = null;
if(data.doc_id=='0')
{
row = $('<tr></tr>').attr("did",did).attr("onclick","GetRowData(this)").appendTo(tbody);
}
else
{
if(currow != null)
{
row = $("#doclist tr:eq("+currow+")");
$(row).html('');
totdocs = currow;
}
}
$('<td></td>').text(totdocs+1).appendTo(row);
$('<td></td>').text(data.docholdername).appendTo(row);
$('<td></td>').attr("dtype",data.doctype).text($("#doctype option[value='"+data.doctype+"']").text()).appendTo(row);
$('<td></td>').attr("id",data.serviceprovider_hidden).text(data.serviceprovider).appendTo(row);
$('<td></td>').attr("title",data.city).text(data.uniqueno).appendTo(row);
$('<td></td>').text(data.yearmonth).appendTo(row);
$('<td></td>').attr("id",data.vendor_id).text((vname.length > 0 ? vname:$("#vendor_id option[value='"+data.vendor_id+"']").text())).appendTo(row);
$('<td></td>').text("").appendTo(row);
}
function GetRowData(drow)
{
currow = $(drow).index();
$("#doctype").val($(drow).find('td').eq(2).attr("dtype"));
$("#doctype").trigger("change");
$("#docholdername").val($(drow).find('td').eq(1).text().trim());
$("#serviceprovider").val($(drow).find('td').eq(3).text().trim());
$("#serviceprovider_hidden").val($(drow).find('td').eq(3).attr("id"));
$("#uniqueno").val($(drow).find('td').eq(4).text().trim());
$("#yearmonth").val($(drow).find('td').eq(5).text().trim());
$("#city").val($(drow).find('td').eq(4).attr("title").trim());
//$("#vendor_id").val($(drow).find('td').eq(6).attr("id"));
ValidateEntry('t');
$("#doc_id").val($(drow).attr("did"));
}
function resetDocForm()
{
validateHidden = false;
document.getElementById('docdetails').reset();
$('#city').val("-1");
$('#vendor_id').empty().append('<option value="-1" selected>SELECT</option>');
currow = null;
}
function UpdateDoc()
{
var jsonString = JSON.stringify($('#docdetails').serializeObject()).substring();
jsonString = '{'+jsonString.substring(1, jsonString.length-1)+',"uuid":"'+$("#uuid").val()+'","usid":"'+$("#usid").val()+'"}';
$.ajax({
url:"doc/updcasedocs",
type:"POST",
contentType: "application/json; charset=utf-8",
data: jsonString, //Stringified Json Object
async: false, //Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation
cache: false, //This will force requested pages not to be cached by the browser
processData:false, //To avoid making query String instead of JSON
success: function(resposeJsonObject){
var dataArray = jQuery.parseJSON(resposeJsonObject);
if(dataArray.status.search("error") > -1)
{
CallMessage(dataArray.result,3000,200,300);
}
else
{
AddDocRow(dataArray.result,dataArray.did,'');
resetDocForm();
}
}
});
}
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};

View File

@@ -1,68 +0,0 @@
var currow=0;
var lastrow=0;
function InitPage()
{
$('form tbody.scrollContent tr').hover(function () {
$('#row'+lastrow).removeClass('rowhover');
ResetRow();
$(this).addClass('rowhover');
}, function () {
$(this).removeClass('rowhover');
});
$('form tbody.scrollContent tr').click(function () {
GetRowData(this);
});
}
function ResetRow()
{
currow=0;
lastrow=$('#casetable tr').length-1;
}
function GetRowData(SelectedRow)
{
/*QueryStr="rand="+Math.round(Math.random()*4+1)+"&uuid="+$("#"+SelectedRow.id+"uuid").val()+"&pid="+$("#"+SelectedRow.id+"portid").val();
var retVal=0; // Legacy commented example retained without removed browser API.
if(retVal==1)
{
$("#"+SelectedRow.id+"col").html("<img src='/matrix/images/edited.png' title='Details has been edited successfully. Please click refresh button to see the changes' />");
}*/
$("#uuid").val($("#"+SelectedRow.id+"uuid").val());
SubmitForm("caseedit", "_blank", "caseGrid");
}
function keyListen(param1,param2,e) {
var keycode = e.keyCode;
if(keycode==13)
{
GetRowData(document.getElementById("row"+currow));
}
else
{
if(keycode==40)
{
currow=currow+1;
if(currow>=$('#casetable tr').length){currow=1;lastrow=$('#casetable tr').length-1;}
}
if(keycode==38)
{
currow=currow-1;
if(currow<=0){currow=$('#casetable tr').length-1;lastrow=1;}
}
$('#row'+currow).addClass('rowhover');
$('#row'+lastrow).removeClass('rowhover');
document.getElementById('row'+currow).focus();
lastrow=currow;
}
}
function callkeydownhandler(evnt) {
var ev = evnt;
var focusedRow = ev.target && ev.target.tagName === "TR" ? ev.target : null;
if ((ev.key === "Enter" || ev.keyCode === 13) && focusedRow) {
ev.preventDefault();
GetRowData(focusedRow);
return;
}
keyListen('','',ev);
}
window.document.addEventListener("keydown", callkeydownhandler, false);

View File

@@ -19,7 +19,7 @@ function GetMoreDetails(SelectedRow)
$("#"+SelectedRow.id+"col").html("<img src='/matrix/images/edited.png' title='Details has been edited successfully. Please click refresh button to see the changes' />");
}*/
$("#uuid").val($("#"+SelectedRow.id+"uuid").val());
SubmitForm("caseedit", "_blank", "caseGrid");
SubmitForm("caseedit", "_blank", "caseGrid");
}
function ValidateEmailSearch()
{

View File

@@ -1,765 +0,0 @@
var records=new Array(1);
var fields=new Array(1);
var recIndx = 0;
var recpos = 0;
var autocut = 0;
var SameAddr=new Array(0);
var AddrElem=new Array(4);
var selectedAddr=-1;
var FocusAfter="customername";
AddrElem[0]=["rv","raddr1","raddr2","raddr3","rlandmark","Rcolony","colr","rcity","rpincode","rphone"];
AddrElem[1]=["ov","companyname","oaddr1","oaddr2","oaddr3","olandmark","Ocolony","colo","ocity","opincode","ophone","extension"];
AddrElem[2]=["pv","paddr1","paddr2","paddr3","plandmark","Pcolony","colp","pcity","ppincode"];
AddrElem[3]=["bankcode","bankcode","bank_branch_id","product","loanamount","apptype","contactperson","specialinst"];
function InitPage()
{
var portField = document.getElementById("portfolio_id");
var initialPortField = document.getElementById("initial-portfolio-id");
var visibleContentsField = document.getElementById("visiblecontents");
var port = initialPortField ? initialPortField.value : (portField ? portField.value : "-1");
var viscontents = visibleContentsField ? visibleContentsField.value : "";
if (viscontents && viscontents.slice(-ColDelim.length) !== ColDelim) {
viscontents += ColDelim;
}
centerDivBoth("formcontainer","H");
HideSections('rtv');
HideSections('otv');
HideSections('section');
UnhideSections(viscontents,ColDelim);
if (portField) {
$(portField).val(port);
}
if(port>0)
{
if(document.getElementById("ajaxmsg") !== null)
{
CallMessage('1001AJX:warning:Another operation is being processed, please wait..',3000,200,300);
return;
}
LoadingMsg("Fetching records, please wait...","ajaxmsg");
RunAjax("GET","punchedrecs","val0="+port+"&val1="+($("#dynamicfields").val())+"&val2="+($("#uuid").val()),1);
}
}
function ValidateSubmitForm(FormName)
{
var Chkresi=document.getElementById('rv');
var Chkoff=document.getElementById('ov');
var Chkprop=document.getElementById('pv');
if(Chkresi.checked || Chkoff.checked || Chkprop.checked || document.getElementById('rtv').checked || document.getElementById('otv').checked || document.getElementById('refv').checked)
{
validate(document.getElementById('applno'),'t','AlphaNumeric');
validate(document.getElementById('bank_branch_id'),'t','');
validate(document.getElementById('product'),'t','');
validate(document.getElementById('customername'),'t','AlphaSpace');
validate(document.getElementById('apptype'),'t','');
if(Chkresi.checked)
{
CheckForm(Chkresi,'raddr1,raddr2,raddr3,rlandmark,colr,rcity,rpincode','t,f,t,f,t,t,f','SplInstruction,SplInstruction,SplInstruction,SplInstruction,SplInstruction,,Pincode');
if(document.getElementById('Rcolony').value=='' || document.getElementById('Rcolony').value=='0')
{
highlightField(document.getElementById('colr'));
}
}
if(Chkoff.checked)
{
CheckForm(Chkoff,'companyname,oaddr1,oaddr2,oaddr3,olandmark,colo,ocity,opincode,department,designation','f,t,f,t,f,t,t,f,f,f','SplInstruction,SplInstruction,SplInstruction,SplInstruction,SplInstruction,SplInstruction,,Pincode,SplInstruction,SplInstruction');
if(document.getElementById('Ocolony').value=='' || document.getElementById('Ocolony').value=='0')
{
highlightField(document.getElementById('colo'));
}
}
if(document.getElementById('rtv').checked)
{
CheckForm(document.getElementById('rtv'),'rphone','t','Phone');
}
if(document.getElementById('otv').checked)
{
CheckForm(document.getElementById('otv'),'ophone','t','Phone');
}
if(Chkprop.checked)
{
CheckForm(Chkprop,'paddr1,paddr2,paddr3,plandmark,colp,pcity,ppincode','t,f,t,f,t,t,f','SplInstruction,SplInstruction,SplInstruction,SplInstruction,SplInstruction,,Pincode');
if(document.getElementById('Pcolony').value=='' || document.getElementById('Pcolony').value=='0')
{
highlightField(document.getElementById('colp'));
}
}
if(document.getElementById('refv').checked)
{
CheckForm(document.getElementById('refv'),'refname1,refaddress1,refcontactno1','t,f,t','AlphaSpace,SplInstruction,Phone');
}
if (invalidFields>0)
{
CallMessage('VLFRM:error:There are one or more error(s) in form. Please correct them and try again.',3000,200,300);
}
else
{
if(document.getElementById("ajaxmsg") !== null)
{
CallMessage('1001AJX:warning:Another operation is being processed, please wait..',3000,200,300);
return;
}
var Qstr=PrepareQStr();
if(document.getElementById("ajaxmsg") !== null)
{
CallMessage('1001AJX:warning:Another operation is being processed, please wait..',3000,200,300);
return false;
}
LoadingMsg("Saving details, please wait...","ajaxmsg");
RunAjax("GET","updatecase",Qstr,2);
}
}
else
{
CallMessage('VLFRM:error:Atleast one address verification is mandatory.',3000,200,300);
}
}
function PrepareQStr()
{
var val0='';
var val1='';
var indx=3;
autocut=$("#autocut").is(":checked") ? 1 : 0;
var lindx=fields[0].length-1;
var cid=$("#case_id").val();
var temp='';
for(indx;indx<lindx;indx++)
{
temp='';
if($("#"+fields[0][indx]).length > 0)
{
if(fields[0][indx]=='rv' || fields[0][indx]=='sradd' || fields[0][indx]=='rtv' ||
fields[0][indx]=='ov' || fields[0][indx]=='soadd' || fields[0][indx]=='otv' || fields[0][indx]=='rco'
|| fields[0][indx]=='pv' || fields[0][indx]=='rcp' || fields[0][indx]=='ocp' || fields[0][indx]=='spadd'|| fields[0][indx]=='refv'|| fields[0][indx]=='docv')
{
temp=$("#"+fields[0][indx]).is(':checked') ? '1':'0';
}
else if(fields[0][indx]=='portfolio_id' || fields[0][indx]=='bank_branch_id' || fields[0][indx]=='company_id' || fields[0][indx]=='branch_id' || fields[0][indx]=='Rcolony' || fields[0][indx]=='Ocolony' || fields[0][indx]=='Pcolony')
{
temp=$("#"+fields[0][indx]).val()=='' ? '0':$("#"+fields[0][indx]).val();
}
else if(fields[0][indx]=='colr' || fields[0][indx]=='colo' || fields[0][indx]=='colp' || fields[0][indx]=='status')
{
temp=$("#"+fields[0][indx]).val();
records[recpos][indx]=temp.replace(/\'/g,'');
continue;
}
else
{
temp="''"+$("#"+fields[0][indx]).val().replace(/,/g, ' ')+"''";
}
val0=val0+fields[0][indx]+',';
val1=val1+temp+",";
records[recpos][indx]=temp.replace(/\'/g,'');
}
else
{
val0=val0+fields[0][indx]+',';
val1=val1+"NULL,";
records[recpos][indx]=temp.replace(/\'/g,'');
}
}
val1=val1.replace(/&/g,'~AmP~');
return "val0="+val0+"&val1="+val1+"&val2="+cid+"&val3="+($("#uuid").val())+"&val4="+autocut+"&val5="+($("#usid").val())+"&val6="+($("#portfolio_id").val())+"&val7="+($("#formmode").val());
}
function GotoRecord(el,searchtype)
{
recno=el.value;
if(recno!='')
{
if(searchtype == 'recno')
{
if(recno > recIndx || recno <=0)
{
CallMessage('1001IRNG:error:Invalid input. Out of range',3000,200,300);
}
else
{
recpos=recno-1;
FillDetails(recpos);
}
}
else
{
for(index = 0; index < records.length; index++ )
{
if( records[index][4] === recno ) {
recpos = index;
FillDetails(recpos);
break;
}
}
}
}
}
function AddNewRecord()
{
if(recIndx== 0 || records[recIndx-1][0]!='0')
{
var cols=fields[0].length;
recIndx = recIndx+1;
recpos = recIndx-1;
records[recpos]=new Array(cols);
records[recpos][0]='0';
records[recpos][1]=$("#portfolio_id").val();
records[recpos][cols-4]='0';
records[recpos][cols-3]=$("#company_id").val();
records[recpos][cols-2]=$("#branch_id").val();
records[recpos][cols-1]='';
records[recpos][2]='******';
}
else
{
recpos=recIndx-1;
}
FillDetails(recpos);
}
function AfterResponse(response,oprID)
{
var rindx=0;
if(oprID==1)
{
$("#ajaxmsg").remove();
if(response.trim().search('Error')==-1)
{
var rows=response.split(RowDelim);
for(rindx=0;rindx<rows.length-1;rindx++)
{
var cindx=0;
var cols=rows[rindx].split(ColDelim);
if(rindx==0)
{
fields[rindx]=new Array(cols.length);
}
else
{
records[rindx-1]=new Array(cols.length);
}
for(cindx=0;cindx<cols.length;cindx++)
{
if(rindx==0)
{
fields[rindx][cindx]=cols[cindx];
}
else
{
records[rindx-1][cindx]=cols[cindx];
}
}
}
}
else
{
CallMessage(response,3000,200,300);
}
recIndx= rindx==0 ? rindx : rindx-1;
$("#recfound").html("<b>( 0 / "+(recIndx==0 ? "0" : recIndx)+" )</b>");
recpos=recIndx==0 ? 0 : recIndx-1;
FillDetails(recpos);
}
else if(oprID==2)
{
collen=fields[0].length;
$("#ajaxmsg").remove();
if(response.trim().search('Error')==-1)
{
if(autocut==1)
{
records[recpos][collen-4]='1';
}
if($("#case_id").val()!='0')
{
findRecord(3);
}
else
{
records[recpos][2]=response.split(ColDelim)[0];
records[recpos][0]=response.split(ColDelim)[1];
records[recpos][collen-1]=response.split(ColDelim)[2];
AddNewRecord();
}
CallMessage('1001IRNG:info:Record updated successfully',3000,200,300);
}
else
{
records[recpos][collen-4]='-1';
CallMessage(response,3000,200,300);
}
}
else if(oprID==19 || oprID==20 || oprID==21 || oprID==22)
{
TabRows=response.split(RowDelim);
for(indx=0;indx<TabRows.length-1;indx++)
{
if($("#portfolio_id").val()==81)
{
var appl = $("#applno").val();
alert('Application number '+appl+' already exists.');
appl= (appl.search('_1') < 0 ? appl+'_1' : appl.split('_')[0]+'_'+(parseInt(appl.split('_')[1])+1));
$("#applno").val(appl);
validate(document.getElementById('applno'),'t','AlphaNumeric');
document.getElementById('applno').focus();
}
else
{
TabCols=TabRows[indx].split(ColDelim);
SameAddr[indx]=new Array(TabCols.length);
for(cindx=0;cindx<TabCols.length;cindx++)
{
SameAddr[indx][cindx]=TabCols[cindx];
}
}
}
SelectAddr(oprID-19);
}
}
function findRecord(arrOpr)
{
tempPos= recpos;
maxLen= recIndx-1;
if(arrOpr==1) tempPos=0;
if(arrOpr==2)
{
if(tempPos>0) tempPos=tempPos-1;
else return false;
}
if(arrOpr==3)
{
if(tempPos<maxLen) tempPos=tempPos+1;
else return false;
}
if(arrOpr==4) tempPos=maxLen;
recpos= tempPos;
FillDetails(recpos);
}
function FillDetails(indx)
{
if(recIndx > 0)
{
document.forms['casedetails'].reset();
$("#recfound").html("<b>( "+(indx+1)+" / "+(recIndx==0 ? "0" : recIndx)+" )</b>");
var findx=0;
for(findx=0;findx<fields[0].length;findx++)
{
if($("#"+fields[0][findx]).length > 0)
{
if(fields[0][findx]=='rv' || fields[0][findx]=='sradd' || fields[0][findx]=='rtv' ||
fields[0][findx]=='ov' || fields[0][findx]=='soadd' || fields[0][findx]=='otv' || fields[0][findx]=='rco'
|| fields[0][findx]=='pv' || fields[0][findx]=='rcp' || fields[0][findx]=='ocp' || fields[0][findx]=='spadd'|| fields[0][findx]=='refv'|| fields[0][findx]=='docv')
{
if(fields[0][findx]=='docv')
{
if($("#"+fields[0][findx]).is(":visible"))
{
$("#"+fields[0][findx]).attr('checked',true);
}
}
else
{
if(records[indx][findx]=='1')
{
$("#"+fields[0][findx]).attr('checked',true);
}
else
{
$("#"+fields[0][findx]).attr('checked',false);
}
}
}
else
{
$("#"+fields[0][findx]).val(records[indx][findx]);
}
}
}
if($("#status").val()=='1')
{
$("#btnsave").hide();
}
else
{
$("#btnsave").show();
}
FireClickEvents();
document.getElementById("applno").focus();
}
else
{
CallMessage('5005MQRY:error:No records found',3000,200,300);
AddNewRecord();
}
}
function FireClickEvents()
{
HandleClick(document.getElementById('rv'));
HandleClick(document.getElementById('ov'));
HandleClick(document.getElementById('rtv'));
HandleClick(document.getElementById('otv'));
HandleClick(document.getElementById('pv'));
HandleClick(document.getElementById('refv'));
}
function FireToggleEvents()
{
ToggleChks((document.getElementById('rv').checked && document.getElementById('ov').checked),'rco'+ColDelim,ColDelim);
ToggleChks((document.getElementById('apptype').value.toUpperCase()!='APPLICANT' && document.getElementById('apptype').value.toUpperCase()!='-1'),'sradd!C0L!soadd!C0L!spadd!C0L!','!C0L!');
ToggleChks((document.getElementById('rv').checked),'rcp'+ColDelim,ColDelim);
ToggleChks((document.getElementById('ov').checked),'ocp'+ColDelim,ColDelim);
}
function HandleClick(el)
{
if(el.id=='rv')
{
setFormValidation(el,'FormPanel2','raddr1,raddr2,raddr3,rlandmark,rcity,colr,rpincode','t,f,t,f,t,t,f','SplInstruction,SplInstruction,SplInstruction,SplInstruction,,SplInstruction,Pincode',document.getElementById('rtv').checked);
EnableDisableFields(el.checked,'raddr1,raddr2,raddr3,rlandmark,colr,rpincode',',');
}
if(el.id=='rtv')
{
setFormValidation(el,'FormPanel2','rphone','t','Phone',document.getElementById('rv').checked);
}
if(el.id=='ov')
{
setFormValidation(el,'FormPanel3','companyname,oaddr1,oaddr2,oaddr3,olandmark,ocity,colo,opincode,department,designation','f,t,f,t,f,t,t,f,f,f','SplInstruction,SplInstruction,SplInstruction,SplInstruction,SplInstruction,,SplInstruction,Pincode,SplInstruction,SplInstruction',document.getElementById('otv').checked);
EnableDisableFields(el.checked,'oaddr1,oaddr2,oaddr3,olandmark,colo,opincode',',');
}
if(el.id=='rco')
{
if(el.checked)
{
AutoFill('rco',1);
}
else
{AutoFill('rco',0);}
}
if(el.id=='otv')
{
setFormValidation(el,'FormPanel3','ophone','t','Phone',document.getElementById('ov').checked);
}
if(el.id=='pv')
{
setFormValidation(el,'FormPanel4','paddr1,paddr2,paddr3,plandmark,pcity,colp,ppincode','t,f,t,f,t,t,f','SplInstruction,SplInstruction,SplInstruction,SplInstruction,,SplInstruction,Pincode',false);
EnableDisableFields(el.checked,'paddr1,paddr2,paddr3,plandmark,colp,ppincode',',');
if(!el.checked)
{
chkrcp=document.getElementById('rcp');
chkrcp.checked=false;
chkocp=document.getElementById('ocp');
chkocp.checked=false;
}
}
if(el.id=='rcp')
{
if(el.checked)
{
AutoFill('rcp',1);
chkocp=document.getElementById('ocp');
chkocp.checked=false;
chkprop=document.getElementById('pv');
chkprop.checked=true;
HandleClick(chkprop);
}
else
{AutoFill('rcp',0);}
}
if(el.id=='ocp')
{
if(el.checked)
{
AutoFill('ocp',1);
chkrcp=document.getElementById('rcp');
chkrcp.checked=false;
chkprop=document.getElementById('pv');
chkprop.checked=true;
HandleClick(chkprop);
}
else
{AutoFill('ocp',0);}
}
if(el.id=='refv')
{
setFormValidation(el,'FormPanel5','refname1,refaddress1,refcontactno1','t,f,t','AlphaSpace,SplInstruction,Phone',false);
}
}
function setFormValidation(Elem,FormPanel,ChildElems,IsRequired,Validation,CounterPartElem)
{
/*if(Elem.checked && !CounterPartElem)
{
hideForm(Elem.id, FormPanel);
}
if(!Elem.checked)
{
CheckForm(Elem,ChildElems,IsRequired,Validation);
if(!CounterPartElem)
{
hideForm(Elem.id, FormPanel);
}
}*/
if(Elem.checked || CounterPartElem)
{
UnhideSections(FormPanel+ColDelim, ColDelim);
}
else
{
HideSections(FormPanel);
}
CheckForm(Elem,ChildElems,IsRequired,Validation);
FireToggleEvents();
}
function CheckForm(Elem,ChildElems,IsRequired,Validation)
{
var Childs=ChildElems.split(",");
var IsChildReq=IsRequired.split(",");
var ValidString=Validation.split(",");
for(Indx=0;Indx<Childs.length;Indx++)
{
validate(document.getElementById(Childs[Indx]),Elem.checked ? IsChildReq[Indx]:'f',ValidString[Indx]);
}
}
function AutoFill(Opt,FillMode)
{
var SourceFields="";
var TargetFields="";
var isSameAdd=false;
if(Opt=='rco')
{
SourceFields="raddr1"+ColDelim+"raddr2"+ColDelim+"raddr3"+ColDelim+"Rcolony"+ColDelim+"colr"+ColDelim+"rcity"+ColDelim+"rlandmark"+ColDelim+"rpincode"+ColDelim+"rphone";
TargetFields="oaddr1"+ColDelim+"oaddr2"+ColDelim+"oaddr3"+ColDelim+"Ocolony"+ColDelim+"colo"+ColDelim+"ocity"+ColDelim+"olandmark"+ColDelim+"opincode"+ColDelim+"ophone";
if(document.getElementById('Rcolony').value==document.getElementById('Ocolony').value)
{
isSameAdd=true;
}
}
else if(Opt=='rcp')
{
SourceFields="raddr1"+ColDelim+"raddr2"+ColDelim+"raddr3"+ColDelim+"Rcolony"+ColDelim+"colr"+ColDelim+"rcity"+ColDelim+"rlandmark"+ColDelim+"rpincode";
TargetFields="paddr1"+ColDelim+"paddr2"+ColDelim+"paddr3"+ColDelim+"Pcolony"+ColDelim+"colp"+ColDelim+"pcity"+ColDelim+"plandmark"+ColDelim+"ppincode";
if(document.getElementById('Rcolony').value==document.getElementById('Pcolony').value)
{
isSameAdd=true;
}
}
else if(Opt=='ocp')
{
SourceFields="oaddr1"+ColDelim+"oaddr2"+ColDelim+"oaddr3"+ColDelim+"Ocolony"+ColDelim+"colo"+ColDelim+"ocity"+ColDelim+"olandmark"+ColDelim+"opincode";
TargetFields="paddr1"+ColDelim+"paddr2"+ColDelim+"paddr3"+ColDelim+"Pcolony"+ColDelim+"colp"+ColDelim+"pcity"+ColDelim+"plandmark"+ColDelim+"ppincode";
if(document.getElementById('Ocolony').value==document.getElementById('Pcolony').value)
{
isSameAdd=true;
}
}
if(FillMode==1)
{
CopyDetails(SourceFields,TargetFields);
}
else if(FillMode==0 && isSameAdd)
{
ClearDetails(TargetFields);
}
}
function ToggleChks(IsVisible,ChildElems,Delim)
{
if(IsVisible)
{
UnhideSections(ChildElems,Delim);
}
else
{
var Childs=ChildElems.split(Delim);
for(indx=0;indx<Childs.length-1;indx++)
{
HideSections(Childs[indx]);
document.getElementById(Childs[indx]).checked=false;
}
}
}
function ClearDetails(TargetFields)
{
if(TargetFields.length!=0)
{
var TargetList=TargetFields.split(ColDelim);
if(TargetList.length==TargetList.length)
{
for(pos=0;pos<TargetList.length;pos++)
{
$("#"+TargetList[pos]).val("");
}
}
}
}
function CopyDetails(SourceFields,TargetFields)
{
if(SourceFields.length!=0 && TargetFields.length!=0)
{
var SourceList=SourceFields.split(ColDelim);
var TargetList=TargetFields.split(ColDelim);
if(SourceList.length==TargetList.length)
{
for(pos=0;pos<SourceList.length;pos++)
{
$("#"+TargetList[pos]).val($("#"+SourceList[pos]).val());
}
}
}
}
function AfterOptSelect(ElemToRemove,OprID)
{
FillSameDet(selectedAddr, OprID);
selectedAddr=-1;
ElemToRemove.parentNode.removeChild(ElemToRemove);
}
function ShowAddrOptions(OprID)
{
var optDiv=document.createElement("div");
var Addr="";
optDiv.setAttribute("id","optDiv");
optDiv.setAttribute("class","FormPanel");
optDiv.setAttribute("style","font-family:Tahoma;overflow:visible");
var OptionPanel="<div id='TablePanel' class='tableContainer'><table border='0' cellspacing='0' width='100%' id='cutlist'><thead class='thead'><tr title='Row Title'><td colspan='2'>Available Addresses</td></tr></thead><tbody class='scrollContent'>";
for(indx=0;indx<SameAddr.length;indx++)
{
OptionPanel=OptionPanel+"<tr><td><input type='radio' name='rb1' id='rb"+indx+"' value='"+indx+"' onclick='selectedAddr=this.value;' /></td>";
OptionPanel=OptionPanel+"<td style='padding-right:5px'>";
for(cindx=0;cindx<4;cindx++)
{
Addr=Addr+" "+SameAddr[indx][cindx];
}
OptionPanel=OptionPanel+""+Addr+"</td></tr>";
Addr="";
}
OptionPanel=OptionPanel+"<tr><td colspan='2'><input type='button' class='button' name='btnok' style='margin-top:5px;float:right' value='OK' id='btnok' accesskey='K' onclick=\"AfterOptSelect(document.getElementById('inptDialog'),"+OprID+");\"";
OptionPanel=OptionPanel+"</tbody></table></div>";
optDiv.innerHTML=OptionPanel;
ShowInputDialog(optDiv,"Select Address","hint","inptDialog");
document.getElementById('rb0').focus();
}
function FillSameDet(AddrIndex,OprID)
{
if(!(AddrIndex < 0))
{
for(cindx=0;cindx<SameAddr[AddrIndex].length;cindx++)
{
$("#"+AddrElem[OprID][cindx+1]).val((SameAddr[AddrIndex][cindx]));
}
document.getElementById(FocusAfter).focus();
ToggleChks((document.getElementById('apptype').value.toUpperCase()!='APPLICANT' && document.getElementById('apptype').value.toUpperCase()!='-1'),'sradd!C0L!soadd!C0L!spadd!C0L!','!C0L!');
}
else
{
document.getElementById(AddrElem[OprID][0]).focus();
if(document.getElementById(AddrElem[OprID][0]).type=='checkbox'){document.getElementById(AddrElem[OprID][0]).checked=false;}
}
}
function SelectAddr(OprID)
{
if(SameAddr.length>1)
{
ShowAddrOptions(OprID);
}
else
{
FillSameDet(0,OprID);
}
}
function FindSameDet(Elm,Visit,focAfter)
{
if($("#case_id").val()!='0' && Visit=='A')
{
return;
}
else
{
FocusAfter=focAfter;
var procFlag=true;
if(Elm.type=='checkbox')
{
procFlag=Elm.checked;
}
if(procFlag)
{
Applno=document.getElementById('applno').value;
if(Applno.length==0)
{
if(Elm.type=='checkbox'){Elm.checked=false;}
CallMessage('VLFRM:error:Please enter application number.',3000,200,300);
document.getElementById('applno').focus();
return false;
}
else
{
SameAddr=new Array(0); // Empty Address Array
oprId=(Visit=='R' ? 19:Visit=='O' ? 20:Visit=='P' ? 21:22);
QryStr="val="+Applno+"&val1="+$("#portfolio_id").val()+"&val2="+oprId;
RunAjax("GET","findsdet",QryStr,oprId);
}
}
}
}
function FindStr(el,elmids,rstfld)
{
el.value=el.value.split('->')[0];
var skey=el.value.trim().toUpperCase();
if(skey!='UNKNOWN' && skey!='-1')
{
var elms=elmids.split(ColDelim);
var indx=0;
for(indx=0;indx<elms.length;indx++)
{
if($("#"+elms[indx]).val().toUpperCase().search(skey)>-1)
{
return true;
}
}
}
else
{
return true;
}
return false;
}
function HandleBlur(el)
{
if(el.id=='rcity' || el.id=='ocity' || el.id=='pcity')
{
var pel= (el.id=='rcity' ? 'Rcolony':(el.id=='ocity' ? 'Ocolony':'Pcolony'));
var cel= (el.id=='rcity' ? 'raddr':(el.id=='ocity' ? 'oaddr':'paddr'));
var hel= (el.id=='rcity' ? 'colr':(el.id=='ocity' ? 'colo':'colp'));
var chk= (el.id=='rcity' ? 'rv':(el.id=='ocity' ? 'ov':'pv'));
if(!FindStr(el,cel+'2!C0L!'+cel+'3'))
{
CallMessage("1001AREA:error:Invalid area.", 3000, 200, 300);
$(el).val("-1");
$("#"+pel).val("");
$("#"+hel).val("");
}
validate(el,document.getElementById(chk).checked ? 't':'f','');
}
if(el.id=='colr' || el.id=='colo' || el.id=='colp')
{
var pel= (el.id=='colr' ? 'rv':(el.id=='colo' ? 'ov':'pv'));
var cel= (el.id=='colr' ? 'raddr':(el.id=='colo' ? 'oaddr':'paddr'));
if(!FindStr(el,cel+'2!C0L!'+cel+'3'))
{
CallMessage("1001AREA:error:Invalid colony.", 3000, 200, 300);
$(el).val("");
}
if(el.value=='')
{
document.getElementsByName(el.id+'_hidden')[0].value='';
}
if(document.getElementsByName(el.id+'_hidden')[0].value=='')
{
el.value='';
}
validate(el,document.getElementById(pel).checked ? 't':'f','SplInstruction');
}
}

View File

@@ -1,425 +0,0 @@
//RowDelim="~R0W~";
//ColDelim="~C0L~";
var SameAddr=new Array(0);
var AddrElem=new Array(4);
var selectedAddr=-1;
var FocusAfter="CustomerName";
AddrElem[0]=["chksresi","ResiAdd1","ResiAdd2","ResiAdd3","ResiLandmark","ResiAdd3_hidden","ResiAdd3_citylist","ResiAdd3_Pincode","ResiPhone"];
AddrElem[1]=["chksoff","CompanyName","OffAdd1","OffAdd2","OffAdd3","OffLandmark","OffAdd3_hidden","OffAdd3_citylist","OffAdd3_Pincode","OffPhone","Extension"];
AddrElem[2]=["chksprop","PropAdd1","PropAdd2","PropAdd3","PropLandmark","PropAdd3_hidden","PropAdd3_citylist","PropAdd3_Pincode"];
AddrElem[3]=["BankCode","BankCode","branchlist","prodlist","LoanAmount","typelist","ContactPerson","splist"];
function SubmitPunching(pageURL,TargetWindow)
{
document.caseDetails.action=pageURL;
document.caseDetails.target=TargetWindow;
document.caseDetails.submit();
}
function FindSameDet(Elm,Visit,focAfter)
{
if($("#FormMode").val()=='2' && Visit=='A')
{
return;
}
else
{
FocusAfter=focAfter;
var procFlag=true;
if(Elm.type=='checkbox')
{
procFlag=Elm.checked;
}
if(procFlag)
{
Applno=document.getElementById('ApplNo').value;
if(Applno.length==0)
{
if(Elm.type=='checkbox'){Elm.checked=false;}
CallMessage('VLFRM:error:Please enter application number.',3000,200,300);
document.getElementById('ApplNo').focus();
return false;
}
else
{
SameAddr=new Array(0); // Empty Address Array
oprId=(Visit=='R' ? 19:Visit=='O' ? 20:Visit=='P' ? 21:22);
QryStr="val="+Applno+"&val1="+$("#portlist").val()+"&val2="+oprId;
RunAjax("GET","findsdet",QryStr,oprId);
}
}
}
}
function copyTelNo(isCopy,SourceElemId,TargetElemId)
{
if(isCopy)
{
var copyStr="/";
if(($("#"+TargetElemId).val().length) > 0)
{
copyStr=$("#"+TargetElemId).val()+"/"+$("#"+SourceElemId).val();
}
else
{
copyStr=$("#"+SourceElemId).val();
}
$("#"+TargetElemId).val(copyStr);
}
}
function SelectAddr(OprID)
{
if(SameAddr.length>1)
{
ShowAddrOptions(OprID);
}
else
{
FillSameDet(0,OprID);
}
}
function FillSameDet(AddrIndex,OprID)
{
if(!(AddrIndex < 0))
{
for(cindx=0;cindx<SameAddr[AddrIndex].length;cindx++)
{
$("#"+AddrElem[OprID][cindx+1]).val((SameAddr[AddrIndex][cindx]));
}
document.getElementById(FocusAfter).focus();
ToggleChks((document.getElementById('typelist').value.toUpperCase()!='APPLICANT' && document.getElementById('typelist').value.toUpperCase()!='-1'),'chksresi!C0L!chksoff!C0L!chksprop!C0L!','!C0L!');
}
else
{
document.getElementById(AddrElem[OprID][0]).focus();
if(document.getElementById(AddrElem[OprID][0]).type=='checkbox'){document.getElementById(AddrElem[OprID][0]).checked=false;}
}
}
function ShowAddrOptions(OprID)
{
var optDiv=document.createElement("div");
var Addr="";
optDiv.setAttribute("id","optDiv");
optDiv.setAttribute("class","FormPanel");
optDiv.setAttribute("style","font-family:Tahoma;overflow:visible");
var OptionPanel="<div id='TablePanel' class='tableContainer'><table border='0' cellspacing='0' width='100%' id='cutlist'><thead class='thead'><tr title='Row Title'><td colspan='2'>Available Addresses</td></tr></thead><tbody class='scrollContent'>";
for(indx=0;indx<SameAddr.length;indx++)
{
OptionPanel=OptionPanel+"<tr><td><input type='radio' name='rb1' id='rb"+indx+"' value='"+indx+"' onclick='selectedAddr=this.value;' /></td>";
OptionPanel=OptionPanel+"<td style='padding-right:5px'>";
for(cindx=0;cindx<4;cindx++)
{
Addr=Addr+" "+SameAddr[indx][cindx];
}
OptionPanel=OptionPanel+""+Addr+"</td></tr>";
Addr="";
}
OptionPanel=OptionPanel+"<tr><td colspan='2'><input type='button' class='button' name='btnok' style='margin-top:5px;float:right' value='OK' id='btnok' accesskey='K' onclick=\"AfterOptSelect(document.getElementById('inptDialog'),"+OprID+");\"";
OptionPanel=OptionPanel+"</tbody></table></div>";
optDiv.innerHTML=OptionPanel;
ShowInputDialog(optDiv,"Select Address","hint","inptDialog");
document.getElementById('rb0').focus();
}
function AfterOptSelect(ElemToRemove,OprID)
{
FillSameDet(selectedAddr, OprID);
selectedAddr=-1;
ElemToRemove.parentNode.removeChild(ElemToRemove);
}
function GatherRequirement(portID)
{
ClearDropDown("branch"+ColDelim+"product",ColDelim);
HideSections("section");
if(portID!=0)
{
QryStr="val0="+portID;
RunAjax("GET","filldds",QryStr,1);
}
}
function AfterResponse(AjaxResponse,OprID)
{
if(OprID==1)
{
ArrangePage(AjaxResponse);
}
else if(OprID==19 || OprID==20 || OprID==21 || OprID==22)
{
TabRows=AjaxResponse.split(RowDelim);
for(indx=0;indx<TabRows.length-1;indx++)
{
TabCols=TabRows[indx].split(ColDelim);
SameAddr[indx]=new Array(TabCols.length);
for(cindx=0;cindx<TabCols.length;cindx++)
{
SameAddr[indx][cindx]=TabCols[cindx];
}
}
SelectAddr(OprID-19);
}
}
function ArrangePage(AjaxResponse)
{
if(AjaxResponse!='')
{
var TempArr=AjaxResponse.split("#BRAN#");
var branch=TempArr[0];
TempArr=TempArr[1].split("#PROD#");
var product=TempArr[0];
var process=TempArr[1];
FillDD("branch",branch,RowDelim,ColDelim);
FillDD("product",product,RowDelim,ColDelim);
UnhideSections(process,ColDelim);
}
}
function ToggleChks(IsVisible,ChildElems,Delim)
{
if(IsVisible)
{
UnhideSections(ChildElems,Delim);
}
else
{
var Childs=ChildElems.split(Delim);
for(indx=0;indx<Childs.length-1;indx++)
{
HideSections(Childs[indx]);
document.getElementById(Childs[indx]).checked=false;
}
}
}
function setFormValidation(Elem,FormPanel,ChildElems,IsRequired,Validation,CounterPartElem)
{
if(Elem.checked && !CounterPartElem)
{
hideForm(Elem.id, FormPanel);
}
if(!Elem.checked)
{
CheckForm(Elem,ChildElems,IsRequired,Validation);
if(!CounterPartElem)
{
hideForm(Elem.id, FormPanel);
}
}
ToggleChks((document.getElementById('chkresi').checked && document.getElementById('chkoffice').checked),'chkrco'+ColDelim,ColDelim);
ToggleChks((document.getElementById('chkresi').checked),'chkrcp'+ColDelim,ColDelim);
ToggleChks((document.getElementById('chkoffice').checked),'chkocp'+ColDelim,ColDelim);
}
function AutoFill(Opt,FillMode)
{
var SourceFields="";
var TargetFields="";
var isSameAdd=false;
if(Opt=='chkrco')
{
SourceFields="ResiAdd1"+ColDelim+"ResiAdd2"+ColDelim+"ResiAdd3"+ColDelim+"ResiAdd3_hidden"+ColDelim+"ResiAdd3_citylist"+ColDelim+"ResiLandmark"+ColDelim+"ResiAdd3_Pincode"+ColDelim+"ResiPhone";
TargetFields="OffAdd1"+ColDelim+"OffAdd2"+ColDelim+"OffAdd3"+ColDelim+"OffAdd3_hidden"+ColDelim+"OffAdd3_citylist"+ColDelim+"OffLandmark"+ColDelim+"OffAdd3_Pincode"+ColDelim+"OffPhone";
if(document.getElementById('ResiAdd3_hidden').value==document.getElementById('OffAdd3_hidden').value)
{
isSameAdd=true;
}
}
else if(Opt=='chkrcp')
{
SourceFields="ResiAdd1"+ColDelim+"ResiAdd2"+ColDelim+"ResiAdd3"+ColDelim+"ResiAdd3_hidden"+ColDelim+"ResiAdd3_citylist"+ColDelim+"ResiLandmark"+ColDelim+"ResiAdd3_Pincode";
TargetFields="PropAdd1"+ColDelim+"PropAdd2"+ColDelim+"PropAdd3"+ColDelim+"PropAdd3_hidden"+ColDelim+"PropAdd3_citylist"+ColDelim+"PropLandmark"+ColDelim+"PropAdd3_Pincode";
if(document.getElementById('ResiAdd3_hidden').value==document.getElementById('PropAdd3_hidden').value)
{
isSameAdd=true;
}
}
else if(Opt=='chkocp')
{
SourceFields="OffAdd1"+ColDelim+"OffAdd2"+ColDelim+"OffAdd3"+ColDelim+"OffAdd3_hidden"+ColDelim+"OffAdd3_citylist"+ColDelim+"OffLandmark"+ColDelim+"OffAdd3_Pincode";
TargetFields="PropAdd1"+ColDelim+"PropAdd2"+ColDelim+"PropAdd3"+ColDelim+"PropAdd3_hidden"+ColDelim+"PropAdd3_citylist"+ColDelim+"PropLandmark"+ColDelim+"PropAdd3_Pincode";
if(document.getElementById('OffAdd3_hidden').value==document.getElementById('PropAdd3_hidden').value)
{
isSameAdd=true;
}
}
if(FillMode==1)
{
CopyDetails(SourceFields,TargetFields);
}
else if(FillMode==0 && isSameAdd)
{
ClearDetails(TargetFields);
}
}
function ClearDetails(TargetFields)
{
if(TargetFields.length!=0)
{
var TargetList=TargetFields.split(ColDelim);
if(TargetList.length==TargetList.length)
{
for(pos=0;pos<TargetList.length;pos++)
{
$("#"+TargetList[pos]).val("");
}
}
}
}
function CopyDetails(SourceFields,TargetFields)
{
if(SourceFields.length!=0 && TargetFields.length!=0)
{
var SourceList=SourceFields.split(ColDelim);
var TargetList=TargetFields.split(ColDelim);
if(SourceList.length==TargetList.length)
{
for(pos=0;pos<SourceList.length;pos++)
{
$("#"+TargetList[pos]).val($("#"+SourceList[pos]).val());
}
}
}
}
function CheckForm(Elem,ChildElems,IsRequired,Validation)
{
var Childs=ChildElems.split(",");
var IsChildReq=IsRequired.split(",");
var ValidString=Validation.split(",");
for(Indx=0;Indx<Childs.length;Indx++)
{
validate(document.getElementById(Childs[Indx]),Elem.checked ? IsChildReq[Indx]:'f',ValidString[Indx]);
}
}
function onLocalityBlur(el,IsRequired)
{
if(el.value=='')
{
document.getElementById(el.id+'_hidden').value='';
}
if(document.getElementById(el.id+'_hidden').value=='')
{
el.value='';
}
validate(el,IsRequired,'SplInstruction');
}
function ValidateSubmitForm(FormName)
{
var Chkresi=document.getElementById('chkresi');
var Chkoff=document.getElementById('chkoffice');
var Chkprop=document.getElementById('chkprop');
if(Chkresi.checked || Chkoff.checked || Chkprop.checked || document.getElementById('chkteler').checked || document.getElementById('chkteleo').checked || document.getElementById('chkref').checked || document.getElementById('chkdoc').checked)
{
validate(document.getElementById('ApplNo'),'t','AlphaNumeric');
validate(document.getElementById('branchlist'),'t','');
validate(document.getElementById('prodlist'),'t','');
validate(document.getElementById('CustomerName'),'t','AlphaSpace');
validate(document.getElementById('typelist'),'t','');
if(Chkresi.checked)
{
CheckForm(Chkresi,'ResiAdd1,ResiAdd2,ResiAdd3,ResiLandmark,ResiAdd3_citylist,ResiAdd3_Pincode','t,f,t,f,t,t','SplInstruction,SplInstruction,SplInstruction,SplInstruction,,Pincode');
if(document.getElementById('ResiAdd3_hidden').value=='' || document.getElementById('ResiAdd3_hidden').value=='0')
{
highlightField(document.getElementById('ResiAdd3'));
}
}
if(Chkoff.checked)
{
CheckForm(Chkoff,'CompanyName,OffAdd1,OffAdd2,OffAdd3,OffLandmark,OffAdd3_citylist,OffAdd3_Pincode,Department,Designation','f,t,f,t,f,t,t,f,f,t','SplInstruction,SplInstruction,SplInstruction,SplInstruction,SplInstruction,,Pincode,SplInstruction,SplInstruction');
if(document.getElementById('OffAdd3_hidden').value=='' || document.getElementById('OffAdd3_hidden').value=='0')
{
highlightField(document.getElementById('OffAdd3'));
}
}
if(document.getElementById('chkteler').checked)
{
CheckForm(document.getElementById('chkteler'),'ResiPhone','t','Phone');
}
if(document.getElementById('chkteleo').checked)
{
CheckForm(document.getElementById('chkteleo'),'OffPhone','t','Phone');
}
if(Chkprop.checked)
{
CheckForm(Chkprop,'PropAdd1,PropAdd2,PropAdd3,PropLandmark,PropAdd3_citylist,PropAdd3_Pincode','t,f,t,f,t,t','SplInstruction,SplInstruction,SplInstruction,SplInstruction,,Pincode');
if(document.getElementById('PropAdd3_hidden').value=='' || document.getElementById('PropAdd3_hidden').value=='0')
{
highlightField(document.getElementById('PropAdd3'));
}
}
if(document.getElementById('chkref').checked)
{
CheckForm(document.getElementById('chkref'),'Ref1Name,Ref1Address,Ref1Contactno','t,f,t','AlphaSpace,SplInstruction,Phone');
}
if (invalidFields>0)
{
CallMessage('VLFRM:error:There are one or more error(s) in form. Please correct them and try again.',3000,200,300);
}
else
{
SubmitForm('casesave','_parent',FormName);
}
}
else
{
CallMessage('VLFRM:error:Atleast one address verification is mandatory.',3000,200,300);
}
}
function HandleClick(el)
{
if(el.id=='chkresi')
{
setFormValidation(el,'FormPanel2','ResiAdd1,ResiAdd2,ResiAdd3,ResiLandmark,ResiAdd3_citylist,ResiAdd3_Pincode','t,f,t,f,t,t,f','SplInstruction,SplInstruction,SplInstruction,SplInstruction,,Pincode',document.getElementById('chkteler').checked);
EnableDisableFields(el.checked,'ResiAdd1,ResiAdd2,ResiAdd3,ResiLandmark,ResiAdd3_Pincode',',');
}
if(el.id=='chkteler')
{
setFormValidation(el,'FormPanel2','ResiPhone','t','Phone',document.getElementById('chkresi').checked);
}
if(el.id=='chkoffice')
{
setFormValidation(el,'FormPanel3','CompanyName,OffAdd1,OffAdd2,OffAdd3,OffLandmark,OffAdd3_citylist,OffAdd3_Pincode,Department,Designation','f,t,f,t,f,t,t,f,f,t','SplInstruction,SplInstruction,SplInstruction,SplInstruction,SplInstruction,,Pincode,SplInstruction,SplInstruction',document.getElementById('chkteleo').checked);
EnableDisableFields(el.checked,'OffAdd1,OffAdd2,OffAdd3,OffLandmark,OffAdd3_Pincode',',');
}
if(el.id=='chkrco')
{
if(el.checked)
{
AutoFill('chkrco',1);
}
else
{AutoFill('chkrco',0);}
}
if(el.id=='chkteleo')
{
setFormValidation(el,'FormPanel3','OffPhone','t','Phone',document.getElementById('chkoffice').checked);
}
if(el.id=='chkprop')
{
setFormValidation(el,'FormPanel4','PropAdd1,PropAdd2,PropAdd3,PropLandmark,PropAdd3_citylist,PropAdd3_Pincode','t,f,t,f,t,t','SplInstruction,SplInstruction,SplInstruction,SplInstruction,,Pincode',false);
EnableDisableFields(el.checked,'PropAdd1,PropAdd2,PropAdd3,PropLandmark,PropAdd3_Pincode',',');
}
if(el.id=='chkrcp')
{
if(el.checked)
{
AutoFill('chkrcp',1);
chkocp=document.getElementById('chkocp');
chkocp.checked=false;
chkprop=document.getElementById('chkprop');
chkprop.checked=true;
HandleClick(chkprop);
}
else
{AutoFill('chkrcp',0);}
}
if(el.id=='chkocp')
{
if(el.checked)
{
AutoFill('chkocp',1);
chkrcp=document.getElementById('chkrcp');
chkrcp.checked=false;
chkprop=document.getElementById('chkprop');
chkprop.checked=true;
HandleClick(chkprop);
}
else
{AutoFill('chkocp',0);}
}
}

View File

@@ -1,403 +0,0 @@
var records=new Array(1);
var fields=new Array(1);
var recIndx = 0;
var recpos = 0;
var FocusAfter="customername";
ajax_list_externalFile = "listservprovider";
var validateHidden = false;
function InitPage(port)
{
centerDivBoth("formcontainer","H");
$("#portfolio_id").val(port);
ManageButtons(true);
$("#btnsave").hide();
if(port>0)
{
if(document.getElementById("ajaxmsg") !== null)
{
CallMessage('1001AJX:warning:Another operation is being processed, please wait..',3000,200,300);
return;
}
LoadingMsg("Fetching records, please wait...","ajaxmsg");
RunAjax("GET","puncheddocrecs","val0="+port+"&val1="+($("#dynamicfields").val()),1);
}
}
function PrepareQStr()
{
var val0='';
var val1='';
var indx=2;
autocut=0;
var lindx=fields[0].length-1;
var cid=$("#case_id").val();
var temp='';
for(indx;indx<lindx;indx++)
{
temp='';
if($("#"+fields[0][indx]).length > 0)
{
if(fields[0][indx]=='docv' || fields[0][indx]=='status')
{
continue;
}
else
{
temp="''"+$("#"+fields[0][indx]).val().replace(/,/g, ' ')+"''";
}
val0=val0+fields[0][indx]+',';
val1=val1+temp+",";
records[recpos][indx]=temp.replace(/\'/g,'');
}
else
{
val0=val0+fields[0][indx]+',';
val1=val1+"NULL,";
records[recpos][indx]=temp.replace(/\'/g,'');
}
}
val1=val1.replace(/&/g,'~AmP~');
return "val0="+val0+"&val1="+val1+"&val2="+cid+"&val3="+($("#uuid").val())+"&val4="+autocut+"&val5="+($("#usid").val())+"&val6="+($("#portfolio_id").val());
}
function GotoRecord(el)
{
recno=el.value;
if(recno!='')
{
if(recno > recIndx || recno <=0)
{
CallMessage('1001IRNG:error:Invalid input. Out of range',3000,200,300);
}
else
{
recpos=recno-1;
FillDetails(recpos);
}
}
}
function AddNewRecord()
{
if(recIndx== 0 || records[recIndx-1][0]!='0')
{
var cols=fields[0].length;
recIndx = recIndx+1;
recpos = recIndx-1;
records[recpos]=new Array(cols);
records[recpos][0]='0';
records[recpos][1]=$("#portfolio_id").val();
records[recpos][cols-4]='0';
records[recpos][cols-3]=$("#company_id").val();
records[recpos][cols-2]=$("#branch_id").val();
records[recpos][cols-1]='';
}
else
{
recpos=recIndx-1;
}
FillDetails(recpos);
}
function AfterResponse(response,oprID)
{
var rindx=0;
if(oprID==1)
{
$("#ajaxmsg").remove();
if(response.trim().search('Error')==-1)
{
var rows=response.split(RowDelim);
for(rindx=0;rindx<rows.length-1;rindx++)
{
var cindx=0;
var cols=rows[rindx].split(ColDelim);
if(rindx==0)
{
fields[rindx]=new Array(cols.length);
}
else
{
records[rindx-1]=new Array(cols.length);
}
for(cindx=0;cindx<cols.length;cindx++)
{
if(rindx==0)
{
fields[rindx][cindx]=cols[cindx];
}
else
{
records[rindx-1][cindx]=cols[cindx];
}
}
}
}
else
{
CallMessage(response,3000,200,300);
}
recIndx= rindx==0 ? rindx : rindx-1;
$("#recfound").html("<b>( 0 / "+(recIndx==0 ? "0" : recIndx)+" )</b>");
recpos=0;
FillDetails(recpos);
}
else if(oprID==2)
{
$("#ajaxmsg").remove();
collen=fields[0].length;
if(response.trim().search('Error')==-1)
{
if(autocut==1)
{
records[recpos][collen-4]='1';
}
if($("#case_id").val()!='0')
{
findRecord(3);
}
else
{
records[recpos][0]=response.split(ColDelim)[0];
records[recpos][collen-1]=response.split(ColDelim)[1];
AddNewRecord();
}
CallMessage('1001IRNG:info:Record updated successfully',3000,200,300);
}
else
{
records[recpos][collen-4]='-1';
CallMessage(response,3000,200,300);
}
}
else if(oprID==3)
{
$("#ajaxmsg").remove();
if(response.trim().search('Error')==-1)
{
CallMessage('1001IRNG:info:Record updated successfully',3000,200,300);
}
else
{
CallMessage(response,3000,200,300);
}
}
else if(oprID==4)
{
if(response.trim().search('Error')==-1)
{
FillDD("vendor_id",response,RowDelim,ColDelim);
if(currow != null)
{
$("#vendor_id").val($("#doclist tr:eq("+currow+")").find('td').eq(6).attr("id"));
}
}
else
{
CallMessage(response,3000,200,300);
}
}
else if(oprID==5)
{
if(response.trim().search('Error')==-1)
{
alert(response);
}
else
{
CallMessage(response,3000,200,300);
}
}
}
function findRecord(arrOpr)
{
tempPos= recpos;
maxLen= recIndx-1;
if(arrOpr==1) tempPos=0;
if(arrOpr==2)
{
if(tempPos>0) tempPos=tempPos-1;
else return false;
}
if(arrOpr==3)
{
if(tempPos<maxLen) tempPos=tempPos+1;
else return false;
}
if(arrOpr==4) tempPos=maxLen;
recpos= tempPos;
FillDetails(recpos);
}
function SearchRecord(elm)
{
var found=false;
var skey=elm.value.trim().toLowerCase();
for(rindx=0;rindx<records.length;rindx++)
{
if(records[rindx][3].trim().toLowerCase().search(skey)>-1)
{
recpos=rindx;
found=true;
FillDetails(recpos);
break;
}
}
if(!found)
{
CallMessage('NOREC1001:error:No record found.',3000,200,300);
}
}
function FillDetails(indx)
{
if(recIndx > 0)
{
CancelEdit();
document.forms['casedetails'].reset();
$("#doclist").html('');
resetDocForm();
$("#recfound").html("<b>( "+(indx+1)+" / "+(recIndx==0 ? "0" : recIndx)+" )</b>");
var cols = fields[0].length;
var findx=0;
for(findx=0;findx < cols;findx++)
{
if($("#"+fields[0][findx]).length > 0)
{
$("#"+fields[0][findx]).val(records[indx][findx]);
}
}
var data = jQuery.parseJSON(records[indx][cols-5].replace('},]}','}]}'));
var tdocs = data.docs.length;
for(indx = 0;indx < tdocs; indx++)
{
var did = data.docs[indx].doc_id;
data.docs[indx].doc_id="0";
AddDocRow(data.docs[indx],did,data.docs[indx].docvendor);
}
document.getElementById("applno").focus();
}
else
{
CallMessage('5005MQRY:error:No records found',3000,200,300);
AddNewRecord();
}
}
function EditBasicDetails()
{
EnableDisableFields(false);
ManageButtons(false);
}
function SaveBasicDetails()
{
if(confirm("Are you sure to update the details?"))
{
var QStr=PrepareQStr();
QStr=QStr+"&val7=2";
if(document.getElementById("ajaxmsg") !== null)
{
CallMessage('1001AJX:warning:Another operation is being processed, please wait..',3000,200,300);
return;
}
LoadingMsg("Updating details, please wait...","ajaxmsg");
RunAjax("POST","updatebdetails",QStr,3);
EnableDisableFields(true);
ManageButtons(true);
}
}
function CancelEdit()
{
SetPrevValues();
EnableDisableFields(true);
ManageButtons(true);
}
function EnableDisableFields(isEnabled)
{
var indx=2;
if(typeof fields[0]!=='undefined')
{
var lindx=fields[0].length-1;
for(indx;indx<lindx;indx++)
{
$("#"+fields[0][indx]).prop("disabled",isEnabled);
}
}
indx=0;
/*$("#applno").prop("disabled",isEnabled);
$("#customername").prop("disabled",isEnabled);
$("#dob").prop("disabled",isEnabled);
$("#loanamount").prop("disabled",isEnabled);
$("#bank_branch_id").prop("disabled",isEnabled);
$("#product").prop("disabled",isEnabled);
$("#apptype").prop("disabled",isEnabled);
$("#category").prop("disabled",isEnabled);*/
}
function SetPrevValues()
{
$("#applno").val(records[recpos][3]);
$("#customername").val(records[recpos][6]);
$("#dob").val(records[recpos][9]);
$("#loanamount").val(records[recpos][5]);
$("#bank_branch_id").val(records[recpos][2]);
$("#product").val(records[recpos][4]);
$("#apptype").val(records[recpos][7]);
$("#category").val(records[recpos][8]);
}
function ManageButtons(bmode)
{
if(bmode)
{
if($("#applno").val().length > 0)
{
$("#btnbedit").show();
$("#btnsave").hide();
$("#section7").show();
}
else
{
$("#btnbedit").hide();
$("#btnsave").show();
$("#section7").hide();
EnableDisableFields(false);
}
$("#btnbsave").hide();
$("#btnbcancel").hide();
}
else
{
$("#btnbedit").hide();
$("#btnbsave").show();
$("#btnbcancel").show();
}
}
function changeLabel(el)
{
$("#uniqueidentifier").html($('option:selected',el).attr("uniqueidentifier"));
$("#sprovider").html($('option:selected',el).attr("sprovider"));
$("#serviceprovider").val($('option:selected',el).attr("defsprovider"));
$("#serviceprovider_hidden").val("0");
if($('option:selected',el).attr("genlist")>0)
{
$("#serviceprovider_citylist").val($('option:selected',el).attr("genlist"));
$("#serviceprovider").attr('onkeyup',"ajax_showOptions(this,event)");
validateHidden = true;
}
else
{
$("#serviceprovider_citylist").val("0");
$("#serviceprovider").removeAttr('onkeyup');
validateHidden = false;
}
$("#uniqueno").attr("onblur","validate(this,'t','"+$('option:selected',el).attr("validuno")+"')");
$("#yearmon").html($('option:selected',el).attr("ymon"));
$("#yearmonth").attr("onblur","validate(this,'f','"+$('option:selected',el).attr("validymon")+"')");
ValidateEntry('f');
GetVerifierList(el);
}
function GetVerifierList(el)
{
$("#vendor_id").empty().append('<option value="-1" selected>SELECT</option>');
if(el.value != '-1')
{
RunAjax("POST","getdocverlist","val0="+el.value,4);
}
}

View File

@@ -0,0 +1,137 @@
(function (window, document) {
"use strict";
const API = Object.freeze({ key: "payload-key", save: "application-save" });
const BOOLEAN_FIELDS = Object.freeze({
residenceVerification: "rv",
residenceTelephoneVerification: "rtv",
officeVerification: "ov",
officeTelephoneVerification: "otv",
propertyVerification: "pv",
referenceVerification: "refv",
documentVerification: "docv",
residenceCoApplicant: "rco",
residenceCoProprietor: "rcp",
officeCoProprietor: "ocp",
sameResidenceAddress: "sradd",
sameOfficeAddress: "soadd",
samePropertyAddress: "spadd",
autoCutOff: "autocut"
});
const VALUE_FIELDS = Object.freeze({
applicationId: "case_id", portfolioId: "portfolio_id", bankBranchId: "bank_branch_id",
applicationNumber: "applno", bankCode: "bankcode", product: "product",
loanAmount: "loanamount", customerName: "customername", fatherName: "fathername",
applicationType: "apptype", category: "category", dateOfBirth: "dob",
contactPerson: "contactperson", mobileNumber: "mobileno", specialInstruction: "specialinst",
residenceAddress1: "raddr1", residenceAddress2: "raddr2", residenceAddress3: "raddr3",
residenceLandmark: "rlandmark", residenceColonyId: "Rcolony", residenceCity: "rcity",
residencePincode: "rpincode", residencePhone: "rphone", companyName: "companyname",
officeAddress1: "oaddr1", officeAddress2: "oaddr2", officeAddress3: "oaddr3",
officeLandmark: "olandmark", officeColonyId: "Ocolony", officeCity: "ocity",
officePincode: "opincode", department: "department", designation: "designation",
officePhone: "ophone", extension: "extension", propertyAddress1: "paddr1",
propertyAddress2: "paddr2", propertyAddress3: "paddr3", propertyLandmark: "plandmark",
propertyColonyId: "Pcolony", propertyCity: "pcity", propertyPincode: "ppincode",
referenceName1: "refname1", referenceAddress1: "refaddress1",
referenceContactNumber1: "refcontactno1", referenceName2: "refname2",
referenceAddress2: "refaddress2", referenceContactNumber2: "refcontactno2",
formMode: "formmode"
});
const INTEGER_FIELDS = new Set(["applicationId", "portfolioId", "bankBranchId", "residenceColonyId",
"officeColonyId", "propertyColonyId", "formMode"]);
const element = (id) => document.getElementById(id);
const value = (id) => {
const field = element(id);
if (!field) return "";
window.CygnusFormValidation.sanitizeElement(field);
return field.value?.trim() ?? "";
};
const integer = (id) => {
const parsed = Number.parseInt(value(id), 10);
return Number.isFinite(parsed) ? parsed : 0;
};
const checked = (id) => Boolean(element(id)?.checked);
function collectDynamicFields() {
const names = value("dynamicfields").split(window.ColDelim || "!C0L!").filter(Boolean);
return names.reduce((result, name) => {
if (/^(?:field(?:[1-9]|1[0-2]|150(?:_2)?)|dtfield1)$/i.test(name) && element(name)) {
result[name] = value(name);
}
return result;
}, {});
}
function collectCase() {
const details = {};
Object.entries(VALUE_FIELDS).forEach(([property, id]) => {
details[property] = INTEGER_FIELDS.has(property) ? integer(id) : value(id);
});
Object.entries(BOOLEAN_FIELDS).forEach(([property, id]) => { details[property] = checked(id); });
details.dynamicFields = collectDynamicFields();
return details;
}
function validateForm() {
const verificationIds = ["rv", "rtv", "ov", "otv", "pv", "refv", "docv"];
if (!verificationIds.some(checked)) {
notify("danger", "APP-4221", "At least one verification type is required.");
return false;
}
const validation = window.CygnusInitiationValidation.validateForm();
[["rv", "Rcolony", "colr"], ["ov", "Ocolony", "colo"], ["pv", "Pcolony", "colp"]]
.forEach(([flag, hidden, visible]) => {
if (checked(flag) && integer(hidden) === 0) window.highlightField(element(visible));
});
if (!validation.valid || document.querySelector(".matrix-validation-error-icon")) {
notify("danger", "APP-4221", "Correct the highlighted fields and submit the application again.");
validation.invalid[0]?.focus();
return false;
}
return true;
}
function notify(type, code, message, referenceId) {
window.CygnusNotifications.show({ type, code, message, referenceId });
}
function applyResult(result, originalApplicationId) {
element("case_id").value = result.applicationId;
if (element("mvcode")) element("mvcode").value = result.mvCode || "";
const currentRecord = window.records?.[window.recpos];
if (currentRecord && !Array.isArray(currentRecord)) {
currentRecord.case_id = result.applicationId;
currentRecord.mvcode = result.mvCode;
}
notify("success", "APP-2001", `Application ${result.mvCode || result.applicationId} saved successfully.`);
if (originalApplicationId === 0 && typeof window.AddNewRecord === "function") window.AddNewRecord();
else if (originalApplicationId > 0 && typeof window.findRecord === "function") window.findRecord(3);
}
async function save(event) {
event?.preventDefault();
if (!validateForm()) return false;
const button = element("btnsave");
if (button?.disabled) return false;
const details = collectCase();
if (button) button.disabled = true;
try {
const envelope = await window.CygnusPayloadCrypto.encrypt(details, { keyUrl: API.key });
const response = await fetch(API.save, { method: "POST", credentials: "same-origin",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(envelope) });
const body = await response.json().catch(() => null);
if (!response.ok || !body?.success) throw body?.message || body || {};
applyResult(body.data, details.applicationId);
} catch (error) {
notify("danger", error.code || "APP-5001",
error.message || "Cygnus could not save the application details.", error.referenceId);
} finally {
if (button) button.disabled = false;
}
return false;
}
window.CygnusInitiation = Object.freeze({ save });
}(window, document));

View File

@@ -0,0 +1,112 @@
(function () {
"use strict";
var currentRow = 0;
var lastRow = 0;
function rows() {
return Array.prototype.slice.call(document.querySelectorAll("#casetable tbody tr"));
}
function rowNumber(row) {
return Number((row.id || "").replace("row", "")) || 0;
}
function setActiveRow(row) {
if (!row) {
return;
}
rows().forEach(function (item) {
item.classList.remove("rowhover");
});
row.classList.add("rowhover");
currentRow = rowNumber(row);
lastRow = currentRow;
row.focus();
}
function hiddenValue(row, suffix) {
var input = document.getElementById(row.id + suffix);
return input ? input.value : "";
}
function submitForm(action, target, formId) {
if (typeof SubmitForm === "function") {
SubmitForm(action, target, formId);
return;
}
var form = document.getElementById(formId);
if (!form) {
return;
}
form.action = action;
form.target = target;
form.submit();
}
function openRow(row) {
if (!row) {
return;
}
var uuid = hiddenValue(row, "uuid");
var portfolioId = hiddenValue(row, "portid");
if (!uuid || !portfolioId) {
return;
}
document.getElementById("uuid").value = uuid;
document.getElementById("portlist").value = portfolioId;
submitForm("caseedit", "_parent", "caseGrid");
}
function moveSelection(direction) {
var allRows = rows();
if (allRows.length === 0) {
return;
}
var nextIndex = currentRow > 0 ? currentRow - 1 + direction : 0;
if (nextIndex < 0) {
nextIndex = allRows.length - 1;
}
if (nextIndex >= allRows.length) {
nextIndex = 0;
}
setActiveRow(allRows[nextIndex]);
}
function handleKeydown(event) {
var row = event.target && event.target.closest ? event.target.closest("#casetable tbody tr") : null;
if (event.key === "Enter" && row) {
event.preventDefault();
openRow(row);
return;
}
if (event.key === "ArrowDown") {
event.preventDefault();
moveSelection(1);
return;
}
if (event.key === "ArrowUp") {
event.preventDefault();
moveSelection(-1);
}
}
function init() {
rows().forEach(function (row) {
row.addEventListener("mouseenter", function () {
setActiveRow(row);
});
row.addEventListener("click", function () {
openRow(row);
});
});
document.addEventListener("keydown", handleKeydown, false);
}
window.CygnusEditCases = {
init: init,
openRow: openRow
};
window.InitPage = init;
}());

View File

@@ -0,0 +1,94 @@
(function (window, document) {
"use strict";
const element = (id) => document.getElementById(id);
const checked = (id) => Boolean(element(id)?.checked);
const requiredWhen = (id) => () => checked(id);
const sectionRule = (id, rule = {}) => Object.assign({ when: requiredWhen(id) }, rule);
const RULES = {
applno: { required: true, format: "AlphaNumeric", requiredMessage: "Application number is required." },
bank_branch_id: { required: true, requiredMessage: "Bank branch is required." },
product: { required: true, requiredMessage: "Product is required." },
customername: { required: true, format: "AlphaSpace", requiredMessage: "Customer name is required." },
apptype: { required: true, requiredMessage: "Application type is required." },
bankcode: { format: "AlphaNumeric" }, fathername: { format: "AlphaSpace" }, dob: { format: "Date" },
mobileno: { format: "AllowWrong" }, loanamount: { format: "LoanAmount" },
contactperson: { format: "AlphaSpace" }, specialinst: { format: "SplInstruction" },
raddr1: sectionRule("rv", { required: true, format: "SplInstruction" }), raddr2: sectionRule("rv", { format: "SplInstruction" }),
raddr3: sectionRule("rv", { required: true, format: "SplInstruction" }), rlandmark: sectionRule("rv", { format: "SplInstruction" }),
rcity: sectionRule("rv", { required: true }), colr: sectionRule("rv", { required: true, format: "SplInstruction" }),
rpincode: sectionRule("rv", { format: "Pincode" }), rphone: sectionRule("rtv", { required: true, format: "Phone" }),
companyname: sectionRule("ov", { format: "SplInstruction" }), oaddr1: sectionRule("ov", { required: true, format: "SplInstruction" }),
oaddr2: sectionRule("ov", { format: "SplInstruction" }), oaddr3: sectionRule("ov", { required: true, format: "SplInstruction" }),
olandmark: sectionRule("ov", { format: "SplInstruction" }), ocity: sectionRule("ov", { required: true }),
colo: sectionRule("ov", { required: true, format: "SplInstruction" }), opincode: sectionRule("ov", { format: "Pincode" }),
department: sectionRule("ov", { format: "SplInstruction" }), designation: sectionRule("ov", { format: "SplInstruction" }),
ophone: sectionRule("otv", { required: true, format: "Phone" }), extension: sectionRule("otv", { format: "Extension" }),
paddr1: sectionRule("pv", { required: true, format: "SplInstruction" }), paddr2: sectionRule("pv", { format: "SplInstruction" }),
paddr3: sectionRule("pv", { required: true, format: "SplInstruction" }), plandmark: sectionRule("pv", { format: "SplInstruction" }),
pcity: sectionRule("pv", { required: true }), colp: sectionRule("pv", { required: true, format: "SplInstruction" }),
ppincode: sectionRule("pv", { format: "Pincode" }), refname1: sectionRule("refv", { required: true, format: "AlphaSpace" }),
refaddress1: sectionRule("refv", { format: "SplInstruction" }),
refcontactno1: sectionRule("refv", { required: true, format: "Phone" }),
refname2: sectionRule("refv", { format: "AlphaSpace" }), refaddress2: sectionRule("refv", { format: "SplInstruction" }),
refcontactno2: sectionRule("refv", { format: "Phone" })
};
const VERIFICATION_GROUPS = Object.freeze({
rv: ["raddr1", "raddr2", "raddr3", "rlandmark", "rcity", "colr", "rpincode"],
rtv: ["rphone"],
ov: ["companyname", "oaddr1", "oaddr2", "oaddr3", "olandmark", "ocity", "colo",
"opincode", "department", "designation"],
otv: ["ophone"],
pv: ["paddr1", "paddr2", "paddr3", "plandmark", "pcity", "colp", "ppincode"],
refv: ["refname1", "refaddress1", "refcontactno1"]
});
function registerDynamicRules(form) {
if (!form) return;
form.querySelectorAll("#FormPanel6 [data-validation-required]").forEach(function (field) {
const label = field.closest(".widget")?.querySelector(".lblcontainer")?.textContent.trim();
RULES[field.id] = {
required: field.dataset.validationRequired === "true",
format: field.dataset.validationFormat || "",
requiredMessage: (label || "This dynamic field") + " is required."
};
});
}
function validateField(field) {
const target = typeof field === "string" ? element(field) : field;
const rule = target && RULES[target.id];
return !target || !rule || window.CygnusFormValidation.validateElement(target, rule);
}
function validateForm() {
return window.CygnusFormValidation.validateRules(RULES);
}
function validateVerification(verificationId) {
const invalid = [];
(VERIFICATION_GROUPS[verificationId] || []).forEach(function (fieldId) {
const field = element(fieldId);
if (!validateField(field)) invalid.push(field);
});
return { valid: invalid.length === 0, invalid: invalid };
}
function bind(form) {
if (!form || form.dataset.initiationValidationBound === "true") return;
registerDynamicRules(form);
form.dataset.initiationValidationBound = "true";
form.addEventListener("focusout", function (event) {
window.CygnusFormValidation.sanitizeElement(event.target);
validateField(event.target);
});
}
window.CygnusInitiationValidation = Object.freeze({
rules: RULES,
bind: bind,
validateField: validateField,
validateVerification: validateVerification,
validateForm: validateForm
});
}(window, document));

View File

@@ -0,0 +1,502 @@
/*
* Case Initiation page behaviour.
*
* This file owns record loading/navigation, verification-section state,
* address copying and duplicate-address lookup. The encrypted JSON save
* workflow is intentionally isolated in application-save.js.
*/
var records=[];
var recIndx = 0;
var recpos = 0;
var SameAddr=[];
var AddrElem=[
["rv","raddr1","raddr2","raddr3","rlandmark","Rcolony","colr","rcity","rpincode","rphone"],
["ov","companyname","oaddr1","oaddr2","oaddr3","olandmark","Ocolony","colo","ocity","opincode","ophone","extension"],
["pv","paddr1","paddr2","paddr3","plandmark","Pcolony","colp","pcity","ppincode"],
["bankcode","bankcode","bank_branch_id","product","loanamount","apptype","contactperson","specialinst"]
];
var selectedAddr=-1;
var FocusAfter="customername";
var CHECKBOX_FIELDS=new Set(["rv","sradd","rtv","ov","soadd","otv","rco","pv","rcp","ocp","spadd","refv","docv"]);
var DUPLICATE_OPERATION={R:19,O:20,P:21,A:22};
var PUNCHED_RECORDS_URL="punchedrecs";
var DUPLICATE_DETAILS_URL="findsdet";
var DUPLICATE_FIELDS={
19:["raddr1","raddr2","raddr3","rlandmark","rcolony","colr","rcity","rpincode","rphone"],
20:["companyname","oaddr1","oaddr2","oaddr3","olandmark","ocolony","colo","ocity","opincode","ophone","extension"],
21:["paddr1","paddr2","paddr3","plandmark","pcolony","colp","pcity","ppincode"],
22:["bankcode","bank_branch_id","product","loanamount","apptype","contactperson","specialinst"]
};
function InitPage()
{
var portField = document.getElementById("portfolio_id");
var initialPortField = document.getElementById("initial-portfolio-id");
var visibleContentsField = document.getElementById("visiblecontents");
var port = initialPortField ? initialPortField.value : (portField ? portField.value : "-1");
var viscontents = visibleContentsField ? visibleContentsField.value : "";
if (viscontents && viscontents.slice(-ColDelim.length) !== ColDelim) {
viscontents += ColDelim;
}
centerDivBoth("formcontainer","H");
HideSections('rtv');
HideSections('otv');
HideSections('section');
UnhideSections(viscontents,ColDelim);
if (portField) {
$(portField).val(port);
}
if(port>0)
{
if(document.getElementById("ajaxmsg") !== null)
{
CygnusNotifications.show({type:"warning",code:"1001AJX",message:"Another operation is being processed, please wait.",duration:3000});
return;
}
LoadingMsg("Fetching records, please wait...","ajaxmsg");
loadPunchedRecords(port,$("#uuid").val());
}
}
function GotoRecord(el,searchtype)
{
var recno=el.value;
if(recno!='')
{
if(searchtype == 'recno')
{
if(recno > recIndx || recno <=0)
{
CygnusNotifications.show({type:"danger",code:"1001IRNG",message:"Invalid input. Out of range",duration:3000});
}
else
{
recpos=recno-1;
FillDetails(recpos);
}
}
else
{
for(var index = 0; index < records.length; index++ )
{
if( records[index].applno === recno ) {
recpos = index;
FillDetails(recpos);
break;
}
}
}
}
}
function AddNewRecord()
{
if(recIndx==0 || String(records[recIndx-1].case_id)!='0')
{
recIndx = recIndx+1;
recpos = recIndx-1;
records[recpos]={case_id:'0',portfolio_id:$("#portfolio_id").val(),status:'0',
company_id:$("#company_id").val(),branch_id:$("#branch_id").val(),uuid:'',mvcode:'******'};
}
else
{
recpos=recIndx-1;
}
FillDetails(recpos);
}
async function loadPunchedRecords(portfolioId,documentCaseId)
{
try
{
var query=new URLSearchParams({portfolioId:portfolioId,documentCaseId:documentCaseId || ""});
var response=await fetch(PUNCHED_RECORDS_URL+"?"+query.toString(),{
method:"GET",credentials:"same-origin",headers:{Accept:"application/json"}
});
var body=await response.json().catch(function(){return null;});
if(!response.ok || !body || !body.success) throw body && body.message ? body.message : {};
records=Array.isArray(body.data && body.data.records) ? body.data.records : [];
recIndx=records.length;
updateRecordCounter(0,recIndx);
recpos=recIndx==0 ? 0 : recIndx-1;
FillDetails(recpos);
}
catch(error)
{
CygnusNotifications.show({type:"danger",code:error.code || "APP-5002",
message:error.message || "Cygnus could not load punched records.",referenceId:error.referenceId});
records=[];recIndx=0;recpos=0;FillDetails(0);
}
finally{$("#ajaxmsg").remove();}
}
function handleDuplicateDetailsResponse(records,oprID)
{
if($("#portfolio_id").val()==81)
{
for(var index=0;index<records.length;index++) incrementDuplicateApplicationNumber();
}
else SameAddr=records.map(function(record){
return DUPLICATE_FIELDS[oprID].map(function(field){return record[field] == null ? "" : record[field];});
});
SelectAddr(oprID-19);
}
async function loadDuplicateDetails(applicationNumber,portfolioId,queryId)
{
try
{
var query=new URLSearchParams({applicationNumber:applicationNumber,portfolioId:portfolioId,queryId:queryId});
var response=await fetch(DUPLICATE_DETAILS_URL+"?"+query.toString(),{
method:"GET",credentials:"same-origin",headers:{Accept:"application/json"}
});
var body=await response.json().catch(function(){return null;});
if(!response.ok || !body || !body.success) throw body && body.message ? body.message : {};
handleDuplicateDetailsResponse(Array.isArray(body.data && body.data.records) ? body.data.records : [],queryId);
}
catch(error)
{
CygnusNotifications.show({type:"danger",code:error.code || "APP-5002",
message:error.message || "Cygnus could not search existing application details.",referenceId:error.referenceId});
SameAddr=[];
SelectAddr(queryId-19);
}
}
function incrementDuplicateApplicationNumber()
{
var appl=$("#applno").val();
CygnusNotifications.show({type:"warning",code:"APP-DUPLICATE",message:"Application number "+appl+" already exists.",duration:3000});
appl=appl.search('_1')<0 ? appl+'_1' : appl.split('_')[0]+'_'+(parseInt(appl.split('_')[1])+1);
$("#applno").val(appl);
CygnusInitiationValidation.validateField(document.getElementById('applno'));
document.getElementById('applno').focus();
}
function findRecord(arrOpr)
{
var tempPos= recpos;
var maxLen= recIndx-1;
if(arrOpr==1) tempPos=0;
if(arrOpr==2)
{
if(tempPos>0) tempPos=tempPos-1;
else return false;
}
if(arrOpr==3)
{
if(tempPos<maxLen) tempPos=tempPos+1;
else return false;
}
if(arrOpr==4) tempPos=maxLen;
recpos= tempPos;
FillDetails(recpos);
}
function FillDetails(indx)
{
if(recIndx > 0)
{
document.forms['casedetails'].reset();
updateRecordCounter(indx+1,recIndx);
Object.keys(records[indx]).forEach(function(fieldName){fillRecordField(fieldName,records[indx][fieldName]);});
$("#btnsave").toggle($("#status").val()!='1');
FireClickEvents();
document.getElementById("applno").focus();
}
else
{
CygnusNotifications.show({type:"danger",code:"5005MQRY",message:"No records found",duration:3000});
AddNewRecord();
}
}
function fillRecordField(fieldName,fieldValue)
{
var field=document.getElementById(fieldName) || dynamicFieldElement(fieldName);
if(!field) return;
if(CHECKBOX_FIELDS.has(fieldName))
{
field.checked=fieldName=='docv' ? $(field).is(":visible") : fieldValue=='1';
return;
}
field.value=fieldValue;
}
function dynamicFieldElement(fieldName)
{
var dynamicFields=document.querySelectorAll("#FormPanel6 [id]");
for(var index=0;index<dynamicFields.length;index++)
if(dynamicFields[index].id.toLowerCase()==fieldName.toLowerCase()) return dynamicFields[index];
return null;
}
function updateRecordCounter(current,total)
{
$("#recfound").html("<b>( "+current+" / "+total+" )</b>");
}
function FireClickEvents()
{
["rv","ov","rtv","otv","pv","refv"].forEach(function(id){HandleClick(document.getElementById(id));});
}
function FireToggleEvents()
{
ToggleChks(document.getElementById('rv').checked && document.getElementById('ov').checked,["rco"]);
var applicationType=document.getElementById('apptype').value.toUpperCase();
ToggleChks(applicationType!='APPLICANT' && applicationType!='-1',["sradd","soadd","spadd"]);
ToggleChks(document.getElementById('rv').checked,["rcp"]);
ToggleChks(document.getElementById('ov').checked,["ocp"]);
}
function HandleClick(el)
{
var handler=VERIFICATION_HANDLERS[el.id];
if(handler) handler(el);
}
var VERIFICATION_HANDLERS={
rv:function(el){
setFormValidation(el,'FormPanel2',document.getElementById('rtv').checked);
EnableDisableFields(el.checked,'raddr1,raddr2,raddr3,rlandmark,colr,rpincode',',');
},
rtv:function(el){setFormValidation(el,'FormPanel2',document.getElementById('rv').checked);},
ov:function(el){
setFormValidation(el,'FormPanel3',document.getElementById('otv').checked);
EnableDisableFields(el.checked,'oaddr1,oaddr2,oaddr3,olandmark,colo,opincode',',');
},
otv:function(el){setFormValidation(el,'FormPanel3',document.getElementById('ov').checked);},
pv:function(el){
setFormValidation(el,'FormPanel4',false);
EnableDisableFields(el.checked,'paddr1,paddr2,paddr3,plandmark,colp,ppincode',',');
if(!el.checked){document.getElementById('rcp').checked=false;document.getElementById('ocp').checked=false;}
},
refv:function(el){setFormValidation(el,'FormPanel5',false);},
rco:function(el){AutoFill('rco',el.checked ? 1 : 0);},
rcp:function(el){handlePropertyCopy(el,'rcp','ocp');},
ocp:function(el){handlePropertyCopy(el,'ocp','rcp');}
};
function handlePropertyCopy(el,copyType,otherCheckboxId)
{
AutoFill(copyType,el.checked ? 1 : 0);
if(!el.checked) return;
document.getElementById(otherCheckboxId).checked=false;
var property=document.getElementById('pv');
property.checked=true;
HandleClick(property);
}
function setFormValidation(Elem,FormPanel,CounterPartElem)
{
if(Elem.checked || CounterPartElem)
{
UnhideSections(FormPanel+ColDelim, ColDelim);
}
else
{
HideSections(FormPanel);
}
CygnusInitiationValidation.validateVerification(Elem.id);
FireToggleEvents();
}
function AutoFill(Opt,FillMode)
{
var mapping=ADDRESS_COPY_MAPPINGS[Opt];
if(!mapping) return;
if(FillMode==1) CopyDetails(mapping.source,mapping.target);
else if(document.getElementById(mapping.sourceColony).value==document.getElementById(mapping.targetColony).value)
ClearDetails(mapping.target);
}
var ADDRESS_COPY_MAPPINGS={
rco:{
source:["raddr1","raddr2","raddr3","Rcolony","colr","rcity","rlandmark","rpincode","rphone"],
target:["oaddr1","oaddr2","oaddr3","Ocolony","colo","ocity","olandmark","opincode","ophone"],
sourceColony:"Rcolony",targetColony:"Ocolony"
},
rcp:{
source:["raddr1","raddr2","raddr3","Rcolony","colr","rcity","rlandmark","rpincode"],
target:["paddr1","paddr2","paddr3","Pcolony","colp","pcity","plandmark","ppincode"],
sourceColony:"Rcolony",targetColony:"Pcolony"
},
ocp:{
source:["oaddr1","oaddr2","oaddr3","Ocolony","colo","ocity","olandmark","opincode"],
target:["paddr1","paddr2","paddr3","Pcolony","colp","pcity","plandmark","ppincode"],
sourceColony:"Ocolony",targetColony:"Pcolony"
}
};
function ToggleChks(IsVisible,ChildElems)
{
if(IsVisible)
{
ChildElems.forEach(function(id){UnhideSections(id+ColDelim,ColDelim);});
}
else
{
ChildElems.forEach(function(id){HideSections(id);document.getElementById(id).checked=false;});
}
}
function ClearDetails(TargetFields)
{
TargetFields.forEach(function(id){document.getElementById(id).value="";});
}
function CopyDetails(SourceFields,TargetFields)
{
SourceFields.forEach(function(id,index){document.getElementById(TargetFields[index]).value=document.getElementById(id).value;});
}
function AfterOptSelect(ElemToRemove,OprID)
{
FillSameDet(selectedAddr, OprID);
selectedAddr=-1;
ElemToRemove.parentNode.removeChild(ElemToRemove);
}
function ShowAddrOptions(OprID)
{
var optDiv=document.createElement("div");
var Addr="";
optDiv.setAttribute("id","optDiv");
optDiv.setAttribute("class","FormPanel");
optDiv.setAttribute("style","font-family:Tahoma;overflow:visible");
var OptionPanel="<div id='TablePanel' class='tableContainer'><table border='0' cellspacing='0' width='100%' id='cutlist'><thead class='thead'><tr title='Row Title'><td colspan='2'>Available Addresses</td></tr></thead><tbody class='scrollContent'>";
for(var indx=0;indx<SameAddr.length;indx++)
{
OptionPanel=OptionPanel+"<tr><td><input type='radio' name='rb1' id='rb"+indx+"' value='"+indx+"' onclick='selectedAddr=this.value;' /></td>";
OptionPanel=OptionPanel+"<td style='padding-right:5px'>";
for(var cindx=0;cindx<4;cindx++)
{
Addr=Addr+" "+escapeHtml(SameAddr[indx][cindx]);
}
OptionPanel=OptionPanel+""+Addr+"</td></tr>";
Addr="";
}
OptionPanel=OptionPanel+"<tr><td colspan='2'><input type='button' class='button' name='btnok' style='margin-top:5px;float:right' value='OK' id='btnok' accesskey='K' onclick=\"AfterOptSelect(document.getElementById('inptDialog'),"+OprID+");\"";
OptionPanel=OptionPanel+"</tbody></table></div>";
optDiv.innerHTML=OptionPanel;
ShowInputDialog(optDiv,"Select Address","hint","inptDialog");
document.getElementById('rb0').focus();
}
function escapeHtml(value)
{
return String(value == null ? "" : value).replace(/[&<>"']/g, function(character) {
return ({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[character];
});
}
function FillSameDet(AddrIndex,OprID)
{
if(!(AddrIndex < 0))
{
for(var cindx=0;cindx<SameAddr[AddrIndex].length;cindx++)
{
$("#"+AddrElem[OprID][cindx+1]).val((SameAddr[AddrIndex][cindx]));
}
document.getElementById(FocusAfter).focus();
var applicationType=document.getElementById('apptype').value.toUpperCase();
ToggleChks(applicationType!='APPLICANT' && applicationType!='-1',["sradd","soadd","spadd"]);
}
else
{
document.getElementById(AddrElem[OprID][0]).focus();
if(document.getElementById(AddrElem[OprID][0]).type=='checkbox'){document.getElementById(AddrElem[OprID][0]).checked=false;}
}
}
function SelectAddr(OprID)
{
if(SameAddr.length>1)
{
ShowAddrOptions(OprID);
}
else if(SameAddr.length===1)
{
FillSameDet(0,OprID);
}
else
{
FillSameDet(-1,OprID);
}
}
function FindSameDet(Elm,Visit,focAfter)
{
if($("#case_id").val()!='0' && Visit=='A')
{
return;
}
else
{
FocusAfter=focAfter;
var procFlag=true;
if(Elm.type=='checkbox')
{
procFlag=Elm.checked;
}
if(procFlag)
{
var Applno=document.getElementById('applno').value;
if(Applno.length==0)
{
if(Elm.type=='checkbox'){Elm.checked=false;}
CygnusNotifications.show({type:"danger",code:"VLFRM",message:"Please enter application number.",duration:3000});
document.getElementById('applno').focus();
return false;
}
else
{
SameAddr=[];
var oprId=DUPLICATE_OPERATION[Visit];
loadDuplicateDetails(Applno,$("#portfolio_id").val(),oprId);
}
}
}
}
function FindStr(el,elmids)
{
el.value=el.value.split('->')[0];
var skey=el.value.trim().toUpperCase();
if(skey!='UNKNOWN' && skey!='-1')
{
for(var indx=0;indx<elmids.length;indx++)
{
if(document.getElementById(elmids[indx]).value.toUpperCase().search(skey)>-1)
{
return true;
}
}
}
else
{
return true;
}
return false;
}
var ADDRESS_SECTIONS={
r:{verification:"rv",city:"rcity",colony:"colr",colonyId:"Rcolony",addressFields:["raddr2","raddr3"]},
o:{verification:"ov",city:"ocity",colony:"colo",colonyId:"Ocolony",addressFields:["oaddr2","oaddr3"]},
p:{verification:"pv",city:"pcity",colony:"colp",colonyId:"Pcolony",addressFields:["paddr2","paddr3"]}
};
function addressSectionFor(fieldId)
{
var keys=Object.keys(ADDRESS_SECTIONS);
for(var index=0;index<keys.length;index++)
{
var section=ADDRESS_SECTIONS[keys[index]];
if(fieldId==section.city || fieldId==section.colony) return section;
}
return null;
}
function HandleBlur(el)
{
var section=addressSectionFor(el.id);
if(!section) return;
if(el.id==section.city)
{
if(!FindStr(el,section.addressFields))
{
CygnusNotifications.show({type:"danger",code:"1001AREA",message:"Invalid area.",duration:3000});
el.value="-1";
document.getElementById(section.colonyId).value="";
document.getElementById(section.colony).value="";
}
CygnusInitiationValidation.validateField(el);
}
if(el.id==section.colony)
{
if(!FindStr(el,section.addressFields))
{
CygnusNotifications.show({type:"danger",code:"1001AREA",message:"Invalid colony.",duration:3000});
el.value="";
}
var colonyId=document.getElementById(section.colonyId);
if(el.value=='') colonyId.value='';
if(colonyId.value=='') el.value='';
CygnusInitiationValidation.validateField(el);
}
}

View File

@@ -0,0 +1,150 @@
(function (window, document) {
"use strict";
const FORMATS = Object.freeze({
Email: /^\S*\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,8}\b\S*$/,
Numeric: /^\d*$/,
AlphaNumeric: /^[a-zA-Z0-9_*\/\-]*$/,
AlphaSpace: /^[a-zA-Z0-9()\/ &]*$/,
LoanAmount: /^[a-zA-Z0-9. ]*$/,
SplInstruction: /^[a-zA-Z0-9():,#@.\-\/ ]*$/,
Remarks: /^[a-zA-Z0-9,(),:+&#@'.\-\/ ]*$/,
Pincode: /^\d{6}$/,
Phone: /^((\d{6,8}|\d{10}|\d{3}-\d{6,8})([\/](\d{6,8}|\d{10}|\d{3}-\d{6,8})){0,2})$/,
Extension: /^\d{3,4}$/
});
const DATE_PATTERN = /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/;
function sanitize(value, options) {
const multiline = Boolean(options && options.multiline);
let sanitized = String(value == null ? "" : value).replace(/\t/g, "");
if (multiline) {
sanitized = sanitized.replace(/\r\n?/g, "\n").replace(/[^\x20-\x7E\n]/g, "");
} else {
sanitized = sanitized.replace(/[\r\n]/g, "").replace(/[^\x20-\x7E]/g, "");
}
return sanitized.trim();
}
function sanitizeElement(element) {
if (!element || typeof element.value !== "string") return "";
const tagName = element.tagName ? element.tagName.toLowerCase() : "";
const inputType = (element.type || "text").toLowerCase();
const sanitizableInput = tagName === "input" &&
["text", "search", "tel", "email", "url", "password"].includes(inputType);
if (tagName !== "textarea" && !sanitizableInput) return element.value;
const sanitized = sanitize(element.value, { multiline: tagName === "textarea" });
if (element.value !== sanitized) element.value = sanitized;
return sanitized;
}
function valueOf(element) {
return element && typeof element.value === "string" ? element.value.trim() : "";
}
function isEmpty(element) {
const value = valueOf(element);
return value === "" || (element.type === "select-one" && value === "-1");
}
function isDate(value) {
const parts = DATE_PATTERN.exec(value);
if (!parts) return false;
const day = Number(parts[1]);
const month = Number(parts[2]);
const year = Number(parts[3]);
if (year < 1900 || year > 2100 || month < 1 || month > 12) return false;
const date = new Date(year, month - 1, day);
return date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day;
}
function matchesFormat(value, format) {
if (!value || !format || format === "AllowWrong") return true;
const normalized = Object.keys(FORMATS).find((name) => name.toLowerCase() === format.toLowerCase());
if (format.toLowerCase() === "date") return isDate(value);
return normalized ? FORMATS[normalized].test(value) : true;
}
function errorHost(element) {
let current = element.parentNode;
let host = current;
while (current && current !== document.body) {
if ((" " + (current.className || "") + " ").indexOf(" inputcontainer ") !== -1) return current;
current = current.parentNode;
}
return host;
}
function clearError(element) {
if (!element) return;
const icon = document.getElementById("err" + element.id);
if (icon && icon.parentNode) icon.parentNode.removeChild(icon);
element.classList.remove("errtxt");
if (element.parentNode) element.parentNode.classList.remove("errdiv");
element.removeAttribute("aria-invalid");
element.removeAttribute("aria-describedby");
if (typeof element.setCustomValidity === "function") element.setCustomValidity("");
}
function showError(element, message) {
if (!element) return;
clearError(element);
const host = errorHost(element);
const icon = document.createElement("img");
icon.src = "/matrix/images/exclamation.png";
icon.id = "err" + element.id;
icon.alt = message;
icon.title = message;
icon.className = "matrix-validation-error-icon" +
(element.type === "select-one" ? " matrix-validation-error-icon--select" : "");
icon.style.cssText = "position:absolute;right:" + (element.type === "select-one" ? "24px" : "5px") +
";top:50%;width:14px;height:14px;transform:translateY(-50%);z-index:3;pointer-events:none";
host.style.position = "relative";
host.appendChild(icon);
if (element.type === "select-one") element.parentNode.classList.add("errdiv");
else element.classList.add("errtxt");
element.setAttribute("aria-invalid", "true");
element.setAttribute("aria-describedby", icon.id);
if (typeof element.setCustomValidity === "function") element.setCustomValidity(message);
}
function validateElement(element, rule) {
if (!element) return true;
sanitizeElement(element);
if (typeof rule.when === "function" && !rule.when()) {
clearError(element);
return true;
}
const required = typeof rule.required === "function" ? rule.required() : Boolean(rule.required);
let message = "";
if (required && isEmpty(element)) message = rule.requiredMessage || "This field is required.";
else if (!isEmpty(element) && !matchesFormat(valueOf(element), rule.format)) {
message = rule.formatMessage || "Enter a valid value.";
}
if (message) showError(element, message);
else clearError(element);
return message === "";
}
function validateLegacy(element, requiredFlag, format) {
return validateElement(element, { required: requiredFlag === "t", format: format });
}
function validateRules(rules) {
const invalid = [];
Object.keys(rules).forEach(function (id) {
const element = document.getElementById(id);
if (!validateElement(element, rules[id])) invalid.push(element);
});
return { valid: invalid.length === 0, invalid: invalid };
}
window.CygnusFormValidation = Object.freeze({
clearError: clearError,
sanitize: sanitize,
sanitizeElement: sanitizeElement,
validateElement: validateElement,
validateLegacy: validateLegacy,
validateRules: validateRules
});
}(window, document));

View File

@@ -0,0 +1,95 @@
(function (window, document) {
"use strict";
const DEFAULT_DURATION = 7000;
const VALID_TYPES = new Set(["success", "info", "warning", "danger"]);
function getHost() {
let host = document.getElementById("cygnus-notifications");
if (!host) {
host = document.createElement("div");
host.id = "cygnus-notifications";
host.className = "position-fixed top-0 start-50 translate-middle-x p-3";
host.style.cssText = "z-index:1085;max-width:720px;width:calc(100% - 2rem)";
host.setAttribute("aria-live", "polite");
host.setAttribute("aria-atomic", "true");
document.body.append(host);
}
return host;
}
function dismiss(alert) {
const bootstrapAlert = window.bootstrap?.Alert;
if (bootstrapAlert) {
bootstrapAlert.getOrCreateInstance(alert).close();
} else {
alert.remove();
}
}
function show(options) {
const settings = options || {};
const type = VALID_TYPES.has(settings.type) ? settings.type : "info";
const host = getHost();
const alert = document.createElement("div");
alert.className = `alert alert-${type} alert-dismissible fade show shadow-sm`;
alert.setAttribute("role", type === "danger" ? "alert" : "status");
if (settings.code) {
const code = document.createElement("strong");
code.textContent = `${settings.code}: `;
alert.append(code);
}
alert.append(document.createTextNode(settings.message || ""));
if (settings.referenceId) {
const reference = document.createElement("small");
reference.className = "d-block mt-1";
reference.textContent = `Reference: ${settings.referenceId}`;
alert.append(reference);
}
if (settings.dismissible !== false) {
const close = document.createElement("button");
close.type = "button";
close.className = "btn-close";
close.setAttribute("aria-label", "Close");
close.addEventListener("click", () => dismiss(alert));
alert.append(close);
}
if (settings.stack === true) host.append(alert);
else host.replaceChildren(alert);
const duration = settings.duration === undefined ? DEFAULT_DURATION : settings.duration;
if (Number.isFinite(duration) && duration > 0) {
window.setTimeout(() => {
if (alert.isConnected) dismiss(alert);
}, duration);
}
return alert;
}
function clear() {
document.getElementById("cygnus-notifications")?.replaceChildren();
}
function showLegacy(serialized, options) {
const text = String(serialized || "");
const firstSeparator = text.indexOf(":");
const secondSeparator = firstSeparator < 0 ? -1 : text.indexOf(":", firstSeparator + 1);
const settings = Object.assign({}, options);
if (secondSeparator > firstSeparator) {
settings.code = text.slice(0, firstSeparator);
const legacyType = text.slice(firstSeparator + 1, secondSeparator).toLowerCase();
settings.type = legacyType === "error" ? "danger" : legacyType;
settings.message = text.slice(secondSeparator + 1);
} else {
settings.type = settings.type || "danger";
settings.message = text;
}
return show(settings);
}
window.CygnusNotifications = Object.freeze({ show, showLegacy, clear });
}(window, document));

View File

@@ -0,0 +1,91 @@
(function (window) {
"use strict";
const keyRequests = new Map();
const encoder = new TextEncoder();
function toBase64Url(bytes) {
let binary = "";
const view = new Uint8Array(bytes);
for (let offset = 0; offset < view.length; offset += 0x8000) {
binary += String.fromCharCode(...view.subarray(offset, offset + 0x8000));
}
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
function fromBase64Url(text) {
const normalized = text.replace(/-/g, "+").replace(/_/g, "/");
const binary = atob(normalized + "=".repeat((4 - normalized.length % 4) % 4));
return Uint8Array.from(binary, (character) => character.charCodeAt(0));
}
function fetchKey(keyUrl) {
if (!keyUrl) {
return Promise.reject(new Error("A payload encryption key URL is required."));
}
if (!keyRequests.has(keyUrl)) {
const request = fetch(keyUrl, {
credentials: "same-origin",
headers: { Accept: "application/json" }
}).then(async (response) => {
const body = await response.json();
if (!response.ok) throw body;
if (!body.keyId || !body.publicKey) {
throw new Error("The payload encryption key response is invalid.");
}
return body;
}).catch((error) => {
keyRequests.delete(keyUrl);
throw error;
});
keyRequests.set(keyUrl, request);
}
return keyRequests.get(keyUrl);
}
async function encrypt(payload, options) {
if (!window.crypto?.subtle) {
throw new Error("Secure payload encryption is not supported by this browser.");
}
const keyInfo = await fetchKey(options?.keyUrl);
const publicKey = await window.crypto.subtle.importKey(
"spki",
fromBase64Url(keyInfo.publicKey),
{ name: "RSA-OAEP", hash: "SHA-256" },
false,
["encrypt"]
);
const aesKey = await window.crypto.subtle.generateKey(
{ name: "AES-GCM", length: 256 }, true, ["encrypt"]
);
const initializationVector = window.crypto.getRandomValues(new Uint8Array(12));
const requestId = window.crypto.randomUUID();
const timestamp = new Date().toISOString();
const additionalData = encoder.encode(`${keyInfo.keyId}|${requestId}|${timestamp}`);
const encryptedPayload = await window.crypto.subtle.encrypt(
{ name: "AES-GCM", iv: initializationVector, additionalData },
aesKey,
encoder.encode(JSON.stringify(payload))
);
const rawKey = await window.crypto.subtle.exportKey("raw", aesKey);
const encryptedKey = await window.crypto.subtle.encrypt(
{ name: "RSA-OAEP" }, publicKey, rawKey
);
return Object.freeze({
keyId: keyInfo.keyId,
encryptedKey: toBase64Url(encryptedKey),
initializationVector: toBase64Url(initializationVector),
encryptedPayload: toBase64Url(encryptedPayload),
requestId,
timestamp
});
}
function clearKeyCache(keyUrl) {
if (keyUrl) keyRequests.delete(keyUrl);
else keyRequests.clear();
}
window.CygnusPayloadCrypto = Object.freeze({ encrypt, clearKeyCache });
}(window));

View File

@@ -5,7 +5,7 @@ import com.cygnus.client.CloudIdentityClient;
import java.time.Duration;
import java.util.logging.Level;
import java.util.logging.Logger;
import matrix.nimble.model.Session;
import lib.models.UserSession;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClientResponseException;
@@ -28,7 +28,7 @@ public class CloudAuthenticationGateway {
this.sessionMapper = sessionMapper;
}
public Session authenticate(String loginId, String password) {
public UserSession authenticate(String loginId, String password) {
try {
Duration blockingTimeout = properties.requestTimeout().plusSeconds(1);
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.format.DateTimeFormatter;
import java.util.List;
import lib.models.UserSession;
import matrix.nimble.model.Session;
import org.springframework.stereotype.Component;
@@ -20,22 +21,42 @@ public class CloudSessionMapper {
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();
target.setUserID(Short.toString(source.userId()));
target.setUsername(source.loginId());
target.setUserDisplayName(source.displayName());
target.setUserGroupID(Short.toString(source.groupId()));
target.setUserGroupName(source.groupName());
target.setBranchID(Short.toString(source.branchId()));
target.setBranchName(source.branchName());
target.setBranchCode(source.branchCode());
target.setBranchLocation(source.branchLocation());
target.setCompanyID(Short.toString(source.companyId()));
target.setCompanyName(source.companyName());
target.setCompanyCode(source.companyCode());
target.setLoginTime(LEGACY_LOGIN_TIME.format(source.loginTime()));
target.setMenuHtml(menuRenderer.render(toLegacyMenu(source.menu())));
target.setUserID(Short.toString(source.getUserId()));
target.setUsername(source.getUsername());
target.setUserDisplayName(source.getUserDisplayName());
target.setUserGroupID(Short.toString(source.getUserGroupId()));
target.setUserGroupName(source.getUserGroupName());
target.setBranchID(Short.toString(source.getBranchId()));
target.setBranchName(source.getBranchName());
target.setBranchCode(source.getBranchCode());
target.setBranchLocation(source.getBranchLocation());
target.setCompanyID(Short.toString(source.getCompanyId()));
target.setCompanyName(source.getCompanyName());
target.setCompanyCode(source.getCompanyCode());
target.setLoginTime(source.getLoginTime());
target.setMenuHtml(source.getMenuHtml());
return target;
}

View File

@@ -2,9 +2,9 @@ package matrix.nimble.controller;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lib.constants.ApplicationError;
import lib.models.ErrorDetails;
import matrix.nimble.model.Session;
import lib.constants.ApplicationMessage;
import lib.models.MessageDetails;
import lib.models.UserSession;
import matrix.services.commons.CommonErrorService;
import matrix.services.commons.CommonService;
import org.springframework.ui.ModelMap;
@@ -26,29 +26,41 @@ public abstract class AbstractAuthenticatedController {
ModelMap model,
HttpSession httpSession,
HttpServletResponse response) {
Session session = commonService.getSession(httpSession);
UserSession session = commonService.getUserSession(httpSession);
if (session == null) {
return denied(model, response, httpSession, ApplicationError.SESSION_REQUIRED);
return denied(model, response, httpSession, ApplicationMessage.SESSION_REQUIRED);
}
if (!commonService.hasPageAccess(session, pageRoute)) {
return denied(model, response, httpSession, ApplicationError.ACCESS_DENIED);
return denied(model, response, httpSession, ApplicationMessage.ACCESS_DENIED);
}
model.addAttribute(CommonService.SESSION_ATTRIBUTE, session);
model.addAttribute(CommonService.USER_SESSION_ATTRIBUTE, session);
return PageAuthorization.granted(session);
}
protected final ApiAuthorization authorizeApiPage(
String pageRoute, HttpSession httpSession) {
UserSession session = commonService.getUserSession(httpSession);
if (session == null) {
return ApiAuthorization.denied(new MessageDetails(ApplicationMessage.SESSION_REQUIRED));
}
if (!commonService.hasPageAccess(session, pageRoute)) {
return ApiAuthorization.denied(new MessageDetails(ApplicationMessage.ACCESS_DENIED));
}
return ApiAuthorization.granted(session);
}
private PageAuthorization denied(
ModelMap model,
HttpServletResponse response,
HttpSession httpSession,
ApplicationError error) {
ApplicationMessage error) {
String viewName = errorService.render(
model, response, httpSession, new ErrorDetails(error));
model, response, httpSession, new MessageDetails(error));
return PageAuthorization.denied(viewName);
}
protected record PageAuthorization(Session session, String viewName) {
private static PageAuthorization granted(Session session) {
protected record PageAuthorization(UserSession session, String viewName) {
private static PageAuthorization granted(UserSession session) {
return new PageAuthorization(session, null);
}
@@ -60,4 +72,16 @@ public abstract class AbstractAuthenticatedController {
return session != null;
}
}
protected record ApiAuthorization(UserSession session, MessageDetails error) {
private static ApiAuthorization granted(UserSession session) {
return new ApiAuthorization(session, null);
}
private static ApiAuthorization denied(MessageDetails error) {
return new ApiAuthorization(null, error);
}
public boolean isGranted() { return session != null; }
}
}

View File

@@ -13,8 +13,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import matrix.nimble.edp.cutoff.model.AutoCutThread;
import matrix.nimble.model.MailboxHandler;
import matrix.nimble.model.MailboxHandler;
import matrix.nimble.model.Session;
import matrix.nimble.model.UploadHandler;
import matrix.nimble.utilities.CommonFunctions;
@@ -40,122 +39,7 @@ import org.springframework.web.multipart.MultipartHttpServletRequest;
@Controller
@SessionAttributes({"Sessvals"})
public class Ajax {
@RequestMapping(value="punchedrecs",method=RequestMethod.GET )
public @ResponseBody String PunchedRecords(@RequestParam String val0,@RequestParam String val1,@RequestParam String val2)
{
val1=(val1.replace(GlobalClass.ColDelim, ","));
String fields="case_id,portfolio_id,mvcode,bank_branch_id,applno,product,loanamount,customername,apptype,category,dob,contactperson,mobileno,raddr1,raddr2,raddr3,rlandmark,Rcolony,rcity,rpincode,rphone,companyname,oaddr1,oaddr2,oaddr3,olandmark,Ocolony,ocity,opincode,department,designation,ophone,extension,paddr1,paddr2,paddr3,plandmark,Pcolony,pcity,ppincode,refname1,refaddress1,refcontactno1,refname2,refaddress2,refcontactno2,rv,rtv,ov,otv,pv,refv,docv,rco,rcp,ocp,specialinst,sradd,soadd,spadd,"+val1+"colr,colo,colp,fathername,bankcode,status,company_id,branch_id,uuid";
DBFunctions DBF=new DBFunctions("1001");
DBF.setProcessFlag(true);
if(val2.trim().length() > 20)
{
val0="uuid='"+val2+"'";
}
else
{
val0="portfolio_id="+val0+" and (cutoffby is null or cutoffby=0)";
}
String response= DBF.FetchRunQuery(24, (val0+GlobalClass.ColDelim+val1+GlobalClass.ColDelim+val2+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
fields=fields.replace(",", GlobalClass.ColDelim);
fields=fields+GlobalClass.RowDelim;
if(DBF.isProcessFlag())
{
response=fields+response;
}
else
{
response=DBF.getErrMsg();
response=fields;
}
return response;
}
@RequestMapping(value="puncheddocrecs",method=RequestMethod.GET )
public @ResponseBody String PunchedDocRecords(@RequestParam String val0,@RequestParam String val1)
{
val1=(val1.replace(GlobalClass.ColDelim, ","));
String fields="case_id,portfolio_id,bank_branch_id,applno,product,loanamount,customername,apptype,category,dob,docv,"+val1+"docs,status,company_id,branch_id,uuid";
DBFunctions DBF=new DBFunctions("1001");
DBF.setProcessFlag(true);
String response= DBF.FetchRunQuery(242, (val0+GlobalClass.ColDelim+val1+GlobalClass.ColDelim+"0"+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
fields=fields.replace(",", GlobalClass.ColDelim);
fields=fields+GlobalClass.RowDelim;
if(DBF.isProcessFlag())
{
response=fields+response;
}
else
{
response=DBF.getErrMsg();
response=fields;
}
return response;
}
//insert into main (portfolio_id,bank_branch_id,mvcode,applno,bankcode,product,loanamount,customername,fathername,apptype,category,dob,contactperson,mobileno,specialinst,rv,sradd,rtv,raddr1,raddr2,raddr3,rlandmark,rcolony,rcity,rpincode,rphone,ov,rco,soadd,otv,companyname,oaddr1,oaddr2,oaddr3,olandmark,ocolony,ocity,opincode,department,designation,ophone,extension,pv,rcp,ocp,spadd,paddr1,paddr2,paddr3,plandmark,pcolony,pcity,ppincode,refv,refname1,refaddress1,refcontactno1,refname2,refaddress2,refcontactno2,docv,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,dtfield1,dtfield2,dtfield3,dtfield4,dtfield5,uuid,receivedate,addedon,addedby,company_id,branch_id) values (val0,val1,'val2','val3','val4','val5','val6','val7','val8','val9','val10','val11','val12','val13','val14',val15,val16,val17,'val18','val19','val20','val21',val22,'val23','val24','val25',val26,val27,val28,val29,'val30','val31','val32','val33','val34',val35,'val36','val37','val38','val39','val40','val41',val42,val43,val44,val45,'val46','val47','val48','val49',val50,'val51','val52',val53,'val54','val55','val56','val57','val58','val59',val60,'val61','val62','val63','val64','val65','val66','val67','val68','val69','val70','val71','val72','val73','val74','val75','val76','val77','val78','val79','val80',val81,val82,val83)
@RequestMapping(value="updatecase",method=RequestMethod.GET )
public @ResponseBody String UpdateRecords(@RequestParam String val0,@RequestParam String val1,@RequestParam String val2,@RequestParam String val3,@RequestParam String val4,@RequestParam String val5,@RequestParam String val6,@RequestParam String val7)
{
String uuid=GlobalClass.GenerateUUID();
String response="";
DBFunctions dbf=new DBFunctions("1001");
dbf.setProcessFlag(true);
val1=val1.replace("~AmP~", "&");
if(val2.equals("0"))
{
val0="mvcode,portfolio_id,"+val0+"receivedate,uuid,addedon,addedby";
val1="''xmvcodex'',"+val6+","+val1+"''"+GlobalClass.DateTime("yyyy/MM/dd", new java.util.Date())+"'',''"+uuid+"'',''"+GlobalClass.DateTime("yyyy/MM/dd HH:mm:ss", new java.util.Date())+"'',"+val5+"";
val0="insert into main ("+val0+") values ("+val1+")";
String [] Qvals=(val0+GlobalClass.ColDelim+"DOCDETAILS"+GlobalClass.ColDelim+val6+GlobalClass.ColDelim+uuid+GlobalClass.ColDelim+val5+GlobalClass.ColDelim+val4+GlobalClass.ColDelim).split(GlobalClass.ColDelim);
dbf.FetchRunQuery(16, Qvals);
if(dbf.isProcessFlag())
{
response=dbf.getProcResult();
if(val4.equals("1")) {
AutoCutThread autoCut = new AutoCutThread();
String [] result = response.split(GlobalClass.ColDelim);
autoCut.setPortfolioid(val6);
autoCut.setUserid(val5);
autoCut.setUuid(result[2]);
autoCut.start();
}
}
else
{
response=dbf.getErrMsg();
}
}
else
{
String [] fields=val0.split(",");
String [] vals=val1.split(",");
val0="";
for(int indx=0;indx<fields.length;indx++)
{
val0=val0+fields[indx]+"="+vals[indx]+",";
}
val0=val0+"addedon=(case when addedby=0 then ''"+GlobalClass.DateTime("yyyy/MM/dd HH:mm:ss", new java.util.Date())+"'' else addedon end),addedby=(case when addedby=0 then "+val5+" else addedby end),lasteditedon=''"+GlobalClass.DateTime("yyyy/MM/dd HH:mm:ss", new java.util.Date())+"'',lasteditedby="+val5;
vals=(val0+GlobalClass.ColDelim+"DOCDETAILS"+GlobalClass.ColDelim+val3+GlobalClass.ColDelim+val6+GlobalClass.ColDelim+val5+GlobalClass.ColDelim+val4+GlobalClass.ColDelim+val7+GlobalClass.ColDelim).split(GlobalClass.ColDelim);
dbf.FetchRunQuery(25, vals);
if(dbf.isProcessFlag())
{
response="success";
if(val4.equals("1")) {
AutoCutThread autoCut = new AutoCutThread();
String [] result = response.split(GlobalClass.ColDelim);
autoCut.setPortfolioid(val6);
autoCut.setUserid(val5);
autoCut.setUuid(val3);
autoCut.start();
}
}
else
{
response=dbf.getErrMsg();
}
}
return response;
}
@RequestMapping(value="uploadservice",method=RequestMethod.POST )
@RequestMapping(value="uploadservice",method=RequestMethod.POST )
public @ResponseBody String UploadMNimbleCases(@RequestParam String params)
{
CommonFunctions Cfunc=new CommonFunctions();
@@ -211,21 +95,6 @@ public class Ajax {
}
return response;
}
@RequestMapping(value="getlocality",method=RequestMethod.POST )
public @ResponseBody String GetLocality(@RequestParam String city, @RequestParam String letters)
{
DBFunctions DBF=new DBFunctions("1001");
DBF.setProcessFlag(true);
String val1="and 1=1";
if(!(city.toUpperCase().equals("-1") || city.toUpperCase().equals("UNKNOWN")))
{
val1="and upper(city)=upper('"+city+"')";
}
String response= DBF.FetchRunQuery(13, (letters.toUpperCase()+GlobalClass.ColDelim+val1+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
response=response.replace(GlobalClass.ColDelim+GlobalClass.RowDelim, GlobalClass.RowDelim);
return response;
}
@RequestMapping(value="listservprovider",method=RequestMethod.POST )
public @ResponseBody String ListServProvider(@RequestParam String city, @RequestParam String letters)
{
@@ -235,16 +104,6 @@ public class Ajax {
response=response.replace(GlobalClass.ColDelim+GlobalClass.RowDelim, GlobalClass.RowDelim);
return response;
}
@RequestMapping(value="findsdet",method=RequestMethod.GET )
public @ResponseBody String FindSameAddr(@RequestParam String val, @RequestParam String val1, @RequestParam String val2)
{
String RecDate=GlobalClass.DateTime("yyyy/MM/dd", new java.util.Date());
DBFunctions DBF=new DBFunctions("1001");
DBF.setProcessFlag(true);
String response= DBF.FetchRunQuery(Integer.parseInt(val2), (val+GlobalClass.ColDelim+val1+GlobalClass.ColDelim+RecDate+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
response=response.replace(GlobalClass.ColDelim+GlobalClass.RowDelim, GlobalClass.RowDelim);
return response;
}
@RequestMapping(value="findbyappno",method=RequestMethod.POST )
public @ResponseBody String FindByApplno(@RequestParam String val0, @RequestParam String val1, @RequestParam String val2, @RequestParam String val3)
{

View File

@@ -4,8 +4,8 @@ import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lib.models.ErrorDetails;
import lib.constants.ApplicationError;
import lib.models.MessageDetails;
import lib.constants.ApplicationMessage;
import matrix.services.commons.CommonErrorService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
@@ -37,7 +37,7 @@ public class ApplicationErrorController {
return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
}
private ErrorDetails details(int status) {
return new ErrorDetails(ApplicationError.fromHttpStatus(status));
private MessageDetails details(int status) {
return new MessageDetails(ApplicationMessage.fromHttpStatus(status));
}
}

View File

@@ -1,62 +0,0 @@
package matrix.nimble.controller;
import java.util.HashMap;
import java.util.Map;
import matrix.nimble.utilities.DBFunctions;
import matrix.nimble.utilities.GlobalClass;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("doc/")
public class DocAjax {
@RequestMapping(value="updcasedocs",method=RequestMethod.POST )
public @ResponseBody String UpdateEmpRecords(@RequestBody String jsonString)
{
String [] qparams=null;
Map<String,String> jsonMap=new HashMap<String, String>();
String [] splitted = (jsonString.replace(":\"\"", ":\"null\"").replace("\",\"","!R0@W@0L!").replace("\":\"","!C@~@L!").replace("{\"", "").replace("\"}", "")).split("!R0@W@0L!");
String query="";
String opron = GlobalClass.DateTime("yyyy/MM/dd",new java.util.Date());
for(int indx=0;indx < splitted.length; indx++)
{
jsonMap.put(splitted[indx].split("!C@~@L!")[0], splitted[indx].split("!C@~@L!")[1]);
}
String opr = jsonMap.get("doc_id").toString().equals("0") ? "ADD DOC":"UPDATE DOC";
if(jsonMap.get("doc_id").toString().equals("0"))
{
query = "INSERT INTO case_documents(uuid, doctype, bank_id, docholdername, serviceprovider,uniqueno, yearmonth,";
query += "city, docvendor, addedby, addedon) values (''"+jsonMap.get("uuid")+"'',"+jsonMap.get("doctype")+",";
query += jsonMap.get("serviceprovider_hidden")+",''"+jsonMap.get("docholdername")+"'',''"+jsonMap.get("serviceprovider")+"'',";
query += "''"+jsonMap.get("uniqueno")+"'',''"+jsonMap.get("yearmonth")+"'',''"+jsonMap.get("city")+"'',";
query += jsonMap.get("vendor_id")+","+jsonMap.get("usid")+",''"+opron+"'')";
}
else
{
query = "update case_documents set doctype=''"+jsonMap.get("doctype")+"'',bank_id="+jsonMap.get("serviceprovider_hidden")+",";
query += "docholdername=''"+jsonMap.get("docholdername")+"'',serviceprovider=''"+jsonMap.get("serviceprovider")+"'',";
query += "uniqueno=''"+jsonMap.get("uniqueno")+"'',yearmonth=''"+jsonMap.get("yearmonth")+"'',";
query += "city=''"+jsonMap.get("city")+"'',docvendor=''"+jsonMap.get("vendor_id")+"'',";
query += "addedby="+jsonMap.get("usid")+",addedon=''"+jsonMap.get("opr")+"'' where doc_id="+jsonMap.get("doc_id");
}
qparams = new String[]{query,jsonMap.get("usid").toString(),opr,opron};
String response="failed";
DBFunctions DBF=new DBFunctions("D001");
DBF.setProcessFlag(true);
DBF.FetchRunQuery(354, qparams);
if(DBF.isProcessFlag())
{
response="{\"status\":\"success\",\"did\":\""+DBF.getProcResult()+"\",\"result\":"+jsonString+"}";
}
else
{
response="{\"status\":\"success\",\"did\":\""+jsonMap.get("doc_id")+"\",\"result\":\""+DBF.getErrMsg()+"\"}";
}
return response;
}
}

View File

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

View File

@@ -1,160 +0,0 @@
package matrix.nimble.edp.punching.controllers;
//servlet libraries
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
//spring libraries
import matrix.nimble.edp.punching.model.CaseDetails;
import matrix.nimble.model.Session;
import matrix.nimble.utilities.ModuleFunctions;
import matrix.nimble.utilities.GlobalClass;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
@Controller
@SessionAttributes({ "Sessvals" })
public class CasePucnhing {
@RequestMapping(value = "caseadd1", method = RequestMethod.POST)
public String OpenAddCases(ModelMap model, HttpServletRequest request,
@ModelAttribute(value = "Sessvals") Session Sessvals) {
CaseDetails caseDetails = new CaseDetails();
caseDetails.setFormMode(1);
caseDetails.setErrMsg("");
model.addAttribute("visibleContents", "");
model.addAttribute("caseDetails", caseDetails);
model.addAttribute("branchlist", FillBranchList("0"));
model.addAttribute("prodlist", FillProductList("0"));
model.addAttribute("citylist", FillCityList("0"));
model.addAttribute("typelist", FillApptypeList("0"));
model.addAttribute("doclist", FillDocList("0"));
model.addAttribute("catlist", FillCatList("0"));
model.addAttribute("Sessvals", Sessvals);
model.addAttribute("portlist", FillPortList(Sessvals.getBranchID()));
return "edp/punching/addcases";
}
@RequestMapping(value = "casesave", method = RequestMethod.POST)
public String SaveCase(ModelMap model, HttpServletRequest request,
@ModelAttribute(value = "Sessvals") Session Sessvals,
@ModelAttribute(value = "caseDetails") CaseDetails caseDet, HttpSession session) {
String DynamicNsessVals = "";
CaseDetails caseDetails = new CaseDetails();
caseDet.setErrCode("1001");
if (caseDet.getDynamicFields() != "") {
String[] DynamicFields = caseDet.getDynamicFields().split(GlobalClass.ColDelim);
for (int indx = 0; indx < DynamicFields.length; indx++) {
// DynamicNsessVals=DynamicNsessVals+request.getParameter(DynamicFields[indx])+Delimeter.ColDelim;
caseDet.InvokeSetter("set" + DynamicFields[indx], request.getParameter(DynamicFields[indx]));
}
}
if (caseDet.getFormMode() == 1 || caseDet.getFormMode() == 2) {
DynamicNsessVals = DynamicNsessVals + "" + Sessvals.getUserID() + GlobalClass.ColDelim;
DynamicNsessVals = DynamicNsessVals + "" + Sessvals.getCompanyID() + GlobalClass.ColDelim;
DynamicNsessVals = DynamicNsessVals + "" + Sessvals.getBranchID();
}
if (!session.getAttribute("UUID").toString().equals(caseDet.getUUID())) {
caseDetails.setProcessFlag(true);
caseDetails.setErrMsg("");
} else {
caseDet.SaveDetails(DynamicNsessVals);
caseDetails.setProcessFlag(caseDet.isProcessFlag());
caseDetails.setErrMsg(caseDet.getErrMsg());
}
String VisibleContents = caseDet.getVisibleContents();
if (caseDetails.isProcessFlag()) {
String UUID = GlobalClass.GenerateUUID();
caseDetails.setUUID(UUID);
session.setAttribute("UUID", UUID);
caseDetails.setErrCode("1001");
caseDetails.setFormMode(caseDet.getFormMode());
caseDetails.setVisibleContents(VisibleContents);
caseDetails.setPortfolioId(caseDet.getPortfolioId());
caseDetails = caseDetails.DynamicHtml(caseDetails, caseDet.getPortfolioId());
caseDetails.setDynamicFields(caseDet.getDynamicFields());
VisibleContents = VisibleContents + "" + caseDetails.getDynamicSection();
model.addAttribute("caseDetails", caseDetails);
} else {
caseDet = caseDet.DynamicHtml(caseDet, caseDet.getPortfolioId());
VisibleContents = VisibleContents + "" + caseDet.getDynamicSection();
model.addAttribute("caseDetails", caseDet);
}
model.addAttribute("visibleContents", VisibleContents);
model.addAttribute("branchlist", FillBranchList(caseDet.getPortfolioId()));
model.addAttribute("prodlist", FillProductList(caseDet.getPortfolioId()));
model.addAttribute("citylist", FillCityList(Sessvals.getBranchID()));
model.addAttribute("typelist", FillApptypeList(Sessvals.getBranchID()));
model.addAttribute("doclist", FillDocList(caseDet.getPortfolioId()));
model.addAttribute("catlist", FillCatList(caseDet.getPortfolioId()));
model.addAttribute("Sessvals", Sessvals);
model.addAttribute("portlist", FillPortList(Sessvals.getBranchID()));
return "edp/punching/addcases";
}
@RequestMapping(value = "casedet", method = RequestMethod.POST)
public String GetRequiredData(ModelMap model, HttpServletRequest request,
@ModelAttribute(value = "Sessvals") Session Sessvals,
@ModelAttribute(value = "caseDetails") CaseDetails caseDet, HttpSession session) {
CaseDetails caseDetails = new CaseDetails();
caseDetails.setPortfolioId(caseDet.getPortfolioId());
caseDetails.setErrCode("1001");
String UUID = GlobalClass.GenerateUUID();
caseDetails.setUUID(UUID);
session.setAttribute("UUID", UUID);
caseDetails.setFormMode(caseDet.getFormMode());
caseDetails = caseDetails.DynamicHtml(caseDetails, caseDet.getPortfolioId());
String VisibleContents = (new ModuleFunctions("1001").GetDDHashString(10,
("10" + GlobalClass.ColDelim + caseDet.getPortfolioId()).split(GlobalClass.ColDelim)))
.replace(GlobalClass.RowDelim, "");
caseDetails.setVisibleContents(VisibleContents);
VisibleContents = (VisibleContents + "" + caseDetails.getDynamicSection())
.replace(GlobalClass.ColDelim + "null", "");
model.addAttribute("visibleContents", VisibleContents);
model.addAttribute("caseDetails", caseDetails);
model.addAttribute("portlist", Sessvals.getBranchID());
model.addAttribute("branchlist", FillBranchList(caseDet.getPortfolioId()));
model.addAttribute("prodlist", FillProductList(caseDet.getPortfolioId()));
model.addAttribute("citylist", FillCityList(Sessvals.getBranchID()));
model.addAttribute("typelist", FillApptypeList(Sessvals.getBranchID()));
model.addAttribute("doclist", FillDocList(caseDet.getPortfolioId()));
model.addAttribute("catlist", FillCatList(caseDet.getPortfolioId()));
model.addAttribute("Sessvals", Sessvals);
model.addAttribute("portlist", FillPortList(Sessvals.getBranchID()));
return "edp/punching/addcases";
}
public String[][] FillPortList(String BranchId) {
return new ModuleFunctions("1001").GetResultArray(3,
(BranchId + GlobalClass.ColDelim).split(GlobalClass.ColDelim));
}
public String[][] FillCityList(String BranchID) {
return new ModuleFunctions("1001").GetResultArray(6, BranchID.split(GlobalClass.ColDelim));
}
public String[][] FillApptypeList(String BranchID) {
return new ModuleFunctions("1001").GetResultArray(8, BranchID.split(GlobalClass.ColDelim));
}
public String[][] FillCatList(String PortfolioID) {
return new ModuleFunctions("1001").GetResultArray(9, PortfolioID.split(GlobalClass.ColDelim));
}
public String[][] FillDocList(String PortfolioID) {
return new ModuleFunctions("1001").GetResultArray(7, PortfolioID.split(GlobalClass.ColDelim));
}
public String[][] FillBranchList(String PortfolioID) {
return new ModuleFunctions("1001").GetResultArray(4, PortfolioID.split(GlobalClass.ColDelim));
}
public String[][] FillProductList(String PortfolioID) {
return new ModuleFunctions("1001").GetResultArray(5, PortfolioID.split(GlobalClass.ColDelim));
}
}

View File

@@ -1,60 +0,0 @@
package matrix.nimble.edp.punching.controllers;
import java.util.HashMap;
import jakarta.servlet.http.HttpServletRequest;
import matrix.nimble.edp.punching.model.CaseGrid;
import matrix.nimble.model.Session;
import matrix.nimble.utilities.GlobalClass;
import matrix.nimble.utilities.ModuleFunctions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
@Controller
@SessionAttributes({ "Sessvals" })
public class EditCasesGrid {
@RequestMapping(value = "editgrid", method = RequestMethod.POST)
public String OpenEditGrid(ModelMap model, HttpServletRequest request,
@ModelAttribute(value = "Sessvals") Session Sessvals) {
String[][] CaseList = null;
CaseGrid CG = new CaseGrid();
model.addAttribute("Sessvals", Sessvals);
model.addAttribute("caseList", CaseList);
model.addAttribute("caseGrid", CG);
model.addAttribute("portlist", FillPortList(Sessvals.getBranchID(), Sessvals.getUserID()));
return "edp/punching/editcases";
}
@RequestMapping(value = "caselist", method = RequestMethod.POST)
public String ListCases(ModelMap model, HttpServletRequest request,
@ModelAttribute(value = "Sessvals") Session Sessvals,
@ModelAttribute(value = "caseGrid") CaseGrid caseGrid) {
CaseGrid CG = new CaseGrid();
CG.setErrCode("1002");
CG.setPortfolioId(caseGrid.getPortfolioId());
String[][] CaseList = CG.FillCaseList(caseGrid.getPortfolioId(), Sessvals.getBranchID());
if (CG.isProcessFlag()) {
model.addAttribute("caseList", CaseList);
model.addAttribute("caseGrid", CG);
} else {
caseGrid.setErrMsg(CG.getErrMsg());
model.addAttribute("caseList", CaseList);
model.addAttribute("caseGrid", caseGrid);
}
model.addAttribute("Sessvals", Sessvals);
model.addAttribute("portlist", FillPortList(Sessvals.getBranchID(), Sessvals.getUserID()));
return "edp/punching/editcases";
}
public String[][] FillPortList(String BranchId, String userId) {
return new ModuleFunctions("1002").GetResultArray(249,
(BranchId + GlobalClass.ColDelim + userId + GlobalClass.ColDelim).split(GlobalClass.ColDelim));
}
}

View File

@@ -1,128 +0,0 @@
package matrix.nimble.edp.punching.controllers;
//servlet libraries
import java.net.URLDecoder;
import jakarta.servlet.http.HttpServletRequest;
//spring libraries
import matrix.nimble.edp.punching.model.PunchingHandler;
import matrix.nimble.model.Session;
import matrix.nimble.utilities.CommonFunctions;
import matrix.nimble.utilities.GlobalClass;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
@Controller
@SessionAttributes({ "Sessvals" })
public class Punching {
@RequestMapping(value = "initdocview", method = RequestMethod.POST)
public String InitDocScreen(ModelMap model, HttpServletRequest request,
@ModelAttribute(value = "Sessvals") Session Sessvals) {
PunchingHandler PH = new PunchingHandler();
PH.setErrCode("1901");
model.addAttribute("branchlist", null);
model.addAttribute("prodlist", null);
model.addAttribute("typelist", null);
model.addAttribute("doclist", null);
model.addAttribute("catlist", null);
model.addAttribute("portfolio_id", "-1");
model.addAttribute("Sessvals", Sessvals);
PH.GetDDValues(240, Sessvals.getBranchID().split(GlobalClass.ColDelim));
model.addAttribute("portlist", PH.getOptionvals());
model.addAttribute("formmode", 0);
model.addAttribute("stat", true);
model.addAttribute("msg", "");
return "edp/punching/initdocs";
}
@RequestMapping(value = "docadd", method = RequestMethod.POST)
public String PunchDocs(ModelMap model, HttpServletRequest request,
@ModelAttribute(value = "Sessvals") Session Sessvals) {
String msg = "";
PunchingHandler PH = new PunchingHandler();
CommonFunctions comFunc = new CommonFunctions();
PH.setErrCode("1901");
PH.setPortfolioid(request.getParameter("portfolio_id"));
PH.setProcessFlag(true);
PH.DocDynamicHtml();
if (PH.isProcessFlag()) {
model.addAttribute("dynamichtml", PH.getDynamicpanel());
model.addAttribute("dynamicfields", PH.getDynamicfields());
model.addAttribute("docdynamichtml", PH.getDocdynamicpanel());
model.addAttribute("docdynamicfields", PH.getDocdynamicfields());
} else {
msg = PH.getErrMsg();
}
PH.GetDDValues(240, Sessvals.getBranchID().split(GlobalClass.ColDelim));
model.addAttribute("portlist", PH.getOptionvals());
PH.GetDDValues(4, PH.getPortfolioid().split(GlobalClass.ColDelim));
model.addAttribute("branchlist", PH.getOptionvals());
PH.GetDDValues(5,
(Sessvals.getBranchID() + GlobalClass.ColDelim + "op.description='DOCUMENT' or op.description='APPTYPE'"
+ GlobalClass.ColDelim).split(GlobalClass.ColDelim));
if (PH.getOptionvals() != null) {
model.addAttribute("typelist", comFunc.GetSubArray("APPTYPE", 2, PH.getOptionvals()));
} else {
model.addAttribute("typelist", null);
}
PH.GetDDValues(241, PH.getPortfolioid().split(GlobalClass.ColDelim));
model.addAttribute("doclist", PH.getOptionvals());
PH.GetDDValues(70,
(PH.getPortfolioid() + GlobalClass.ColDelim + "op.description='CATEGORY' or op.description='PRODUCT'"
+ GlobalClass.ColDelim).split(GlobalClass.ColDelim));
if (PH.getOptionvals() != null) {
model.addAttribute("prodlist", comFunc.GetSubArray("PRODUCT", 2, PH.getOptionvals()));
model.addAttribute("catlist", comFunc.GetSubArray("CATEGORY", 2, PH.getOptionvals()));
} else {
model.addAttribute("prodlist", null);
model.addAttribute("catlist", null);
}
model.addAttribute("portfolio_id", PH.getPortfolioid());
model.addAttribute("usid", Sessvals.getUserID());
model.addAttribute("Sessvals", Sessvals);
model.addAttribute("formmode", 1);
model.addAttribute("stat", PH.isProcessFlag());
model.addAttribute("msg", msg);
return "edp/punching/initdocs";
}
@RequestMapping(value = "addeditdoc", method = RequestMethod.POST)
public String AddEditDocs(@RequestParam String val0, @RequestParam String val1, @RequestParam String val2,
@RequestParam String val3, @RequestParam String val4, @RequestParam String val5, @RequestParam String val6,
@RequestParam String val7, @RequestParam String val8, @RequestParam String val9,
@RequestParam String val10) {
String retval = "success";
try {
// System.out.println(URLDecoder.decode(val0,"UTF-8"));
// System.out.println(URLDecoder.decode(val1,"UTF-8"));
// System.out.println(URLDecoder.decode(val2,"UTF-8"));
// System.out.println(URLDecoder.decode(val3,"UTF-8"));
// System.out.println(URLDecoder.decode(val4,"UTF-8"));
// System.out.println(URLDecoder.decode(val6,"UTF-8"));
// System.out.println(URLDecoder.decode(val7,"UTF-8"));
// System.out.println(URLDecoder.decode(val8,"UTF-8"));
// System.out.println(URLDecoder.decode(val9,"UTF-8"));
// System.out.println(URLDecoder.decode(val10,"UTF-8"));
PunchingHandler PH = new PunchingHandler();
PH.setErrCode("1902");
PH.setProcessFlag(true);
PH.AddEditDocs(val0, val1, val2, val3, val4, val6, val7, val8, val9, val10);
} catch (Exception exce) {
retval = exce.getMessage();
}
return retval;
}
}

View File

@@ -6,26 +6,182 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpServletResponse;
import matrix.nimble.controller.AbstractAuthenticatedController;
import matrix.nimble.model.Session;
import lib.models.UserSession;
import matrix.services.commons.CommonService;
import matrix.services.edp.PunchingService;
import matrix.services.commons.CommonErrorService;
import lib.models.CasePunching;
import lib.models.ApplicationDetails;
import lib.models.ApiResponse;
import lib.models.ApplicationSaveData;
import lib.models.ApplicationSaveResult;
import lib.models.CaseSaveRequest;
import lib.models.MessageDetails;
import lib.models.PunchedRecordsData;
import lib.models.DuplicateDetailsData;
import lib.models.LocalityData;
import matrix.nimble.edp.punching.model.CaseGrid;
import lib.constants.ApplicationMessage;
import matrix.nimble.security.PayloadCryptoService;
import lib.exceptions.ApplicationException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@Controller
public class PunchingController extends AbstractAuthenticatedController {
private static final Logger LOGGER = Logger.getLogger(PunchingController.class.getName());
private static final String INIT_VIEW_ROUTE = "initview";
private static final String CASE_ADD_ROUTE = "caseadd";
private static final String CASE_EDIT_ROUTE = "caseedit";
private static final String DUPLICATE_DETAILS_ROUTE = "findsdet";
private static final String LOCALITY_ROUTE = "getlocality";
private static final String EDIT_GRID_ROUTE = "editgrid";
private final PunchingService punchingService;
private final PayloadCryptoService cryptoService;
public PunchingController(CommonService commonService, CommonErrorService errorService,
PunchingService punchingService) {
PunchingService punchingService, PayloadCryptoService cryptoService) {
super(commonService, errorService);
this.punchingService = punchingService;
this.cryptoService = cryptoService;
}
@RequestMapping(value = "payload-key", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<?> caseSaveKey(HttpSession httpSession) {
ApiAuthorization authorization = authorizeApiPage(INIT_VIEW_ROUTE, httpSession);
if (!authorization.isGranted()) return error(authorization.error());
return ResponseEntity.ok(Map.of(
"keyId", cryptoService.keyId(),
"algorithm", "RSA-OAEP-256",
"publicKey", cryptoService.encodedPublicKey()));
}
@RequestMapping(value = "punchedrecs", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<ApiResponse<PunchedRecordsData>> punchedRecords(
@RequestParam("portfolioId") Short portfolioId,
@RequestParam(value = "documentCaseId", required = false) String documentCaseId,
HttpSession httpSession) {
ApiAuthorization authorization = authorizeApiPage(INIT_VIEW_ROUTE, httpSession);
if (!authorization.isGranted()) {
return ResponseEntity.status(authorization.error().getHttpStatus())
.body(ApiResponse.failure(authorization.error()));
}
try {
PunchedRecordsData data = punchingService.loadPunchedRecords(
portfolioId, documentCaseId, authorization.session());
return ResponseEntity.ok(ApiResponse.success(
data, new MessageDetails(ApplicationMessage.APPLICATIONS_LOADED)));
} catch (ApplicationException exception) {
LOGGER.log(Level.WARNING, "Punched records were rejected", exception);
MessageDetails details = new MessageDetails(exception.getApplicationMessage());
return ResponseEntity.status(details.getHttpStatus()).body(ApiResponse.failure(details));
} catch (RuntimeException exception) {
LOGGER.log(Level.SEVERE, "Unable to load punched records", exception);
MessageDetails details = new MessageDetails(ApplicationMessage.INTERNAL_SERVER_ERROR);
return ResponseEntity.status(details.getHttpStatus()).body(ApiResponse.failure(details));
}
}
@RequestMapping(value = DUPLICATE_DETAILS_ROUTE, method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<ApiResponse<DuplicateDetailsData>> findDuplicateDetails(
@RequestParam("applicationNumber") String applicationNumber,
@RequestParam("portfolioId") Short portfolioId,
@RequestParam("queryId") Integer queryId,
HttpSession httpSession) {
ApiAuthorization authorization = authorizeApiPage(INIT_VIEW_ROUTE, httpSession);
if (!authorization.isGranted()) {
return ResponseEntity.status(authorization.error().getHttpStatus())
.body(ApiResponse.failure(authorization.error()));
}
try {
DuplicateDetailsData data = punchingService.findDuplicateDetails(
applicationNumber, portfolioId, queryId, authorization.session());
return ResponseEntity.ok(ApiResponse.success(
data, new MessageDetails(ApplicationMessage.APPLICATIONS_LOADED)));
} catch (ApplicationException exception) {
LOGGER.log(Level.WARNING, "Duplicate detail search was rejected", exception);
MessageDetails details = new MessageDetails(exception.getApplicationMessage());
return ResponseEntity.status(details.getHttpStatus()).body(ApiResponse.failure(details));
} catch (RuntimeException exception) {
LOGGER.log(Level.SEVERE, "Unable to search duplicate details", exception);
MessageDetails details = new MessageDetails(ApplicationMessage.INTERNAL_SERVER_ERROR);
return ResponseEntity.status(details.getHttpStatus()).body(ApiResponse.failure(details));
}
}
@RequestMapping(value = LOCALITY_ROUTE, method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<ApiResponse<LocalityData>> findLocalities(
@RequestParam("city") String city,
@RequestParam("letters") String letters,
HttpSession httpSession) {
ApiAuthorization authorization = authorizeApiPage(INIT_VIEW_ROUTE, httpSession);
if (!authorization.isGranted()) {
return ResponseEntity.status(authorization.error().getHttpStatus())
.body(ApiResponse.failure(authorization.error()));
}
try {
LocalityData data = punchingService.findLocalities(city, letters, authorization.session());
return ResponseEntity.ok(ApiResponse.success(
data, new MessageDetails(ApplicationMessage.APPLICATIONS_LOADED)));
} catch (ApplicationException exception) {
LOGGER.log(Level.WARNING, "Locality search was rejected", exception);
MessageDetails details = new MessageDetails(exception.getApplicationMessage());
return ResponseEntity.status(details.getHttpStatus()).body(ApiResponse.failure(details));
} catch (RuntimeException exception) {
LOGGER.log(Level.SEVERE, "Unable to search localities", exception);
MessageDetails details = new MessageDetails(ApplicationMessage.INTERNAL_SERVER_ERROR);
return ResponseEntity.status(details.getHttpStatus()).body(ApiResponse.failure(details));
}
}
@RequestMapping(value = "application-save", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<ApiResponse<ApplicationSaveData>> saveApplication(
@RequestBody CaseSaveRequest request, HttpSession httpSession) {
ApiAuthorization authorization = authorizeApiPage(INIT_VIEW_ROUTE, httpSession);
if (!authorization.isGranted()) return applicationError(authorization.error());
try {
ApplicationDetails details = cryptoService.decrypt(request, ApplicationDetails.class);
ApplicationSaveResult saved = punchingService.saveApplication(details, authorization.session());
return ResponseEntity.ok(ApiResponse.success(
new ApplicationSaveData(saved.getOperation(), saved.getApplicationId(), saved.getMvCode()),
new MessageDetails(ApplicationMessage.APPLICATION_SAVED)));
} catch (ApplicationException exception) {
LOGGER.log(Level.WARNING, "Application save was rejected", exception);
return applicationError(new MessageDetails(exception.getApplicationMessage()));
} catch (RuntimeException exception) {
LOGGER.log(Level.SEVERE, "Unexpected case-save failure", exception);
return applicationError(new MessageDetails(ApplicationMessage.APPLICATION_SAVE_FAILED));
}
}
private ResponseEntity<?> error(MessageDetails details) {
return ResponseEntity.status(details.getHttpStatus()).body(details);
}
private ResponseEntity<ApiResponse<ApplicationSaveData>> applicationError(MessageDetails details) {
return ResponseEntity.status(details.getHttpStatus())
.body(ApiResponse.failure(details));
}
@RequestMapping(value = INIT_VIEW_ROUTE, method = RequestMethod.POST)
@@ -38,16 +194,15 @@ public class PunchingController extends AbstractAuthenticatedController {
if (!authorization.isGranted()) {
return authorization.viewName();
}
Session Sessvals = authorization.session();
UserSession userSession = authorization.session();
model.addAttribute("model", punchingService.init(
Sessvals.getBranchID(), Sessvals.getUserID(), null, "xxx"));
model.addAttribute("Sessvals", Sessvals);
userSession.getBranchId(), userSession.getUserId(), null, null));
return "edp/punching/initcase";
}
@RequestMapping(value = "caseadd", method = RequestMethod.POST)
public String addCase(
@RequestMapping(value = CASE_ADD_ROUTE, method = RequestMethod.POST)
public String prepareNewApplication(
@ModelAttribute("model") CasePunching submitted,
ModelMap model,
HttpSession httpSession,
@@ -58,16 +213,15 @@ public class PunchingController extends AbstractAuthenticatedController {
return authorization.viewName();
}
Session session = authorization.session();
model.addAttribute("model", punchingService.addCase(
submitted, session.getBranchID(), session.getUserID()));
model.addAttribute("Sessvals", session);
UserSession session = authorization.session();
model.addAttribute("model", punchingService.prepareNewApplication(
submitted, session.getBranchId(), session.getCompanyId(), session.getUserId()));
return "edp/punching/initcase";
}
@RequestMapping(value = "caseedit", method = RequestMethod.POST)
public String editCase(
@RequestParam("PortfolioId") Integer portfolioId,
@RequestMapping(value = CASE_EDIT_ROUTE, method = RequestMethod.POST)
public String prepareApplicationEdit(
@RequestParam("PortfolioId") Short portfolioId,
@RequestParam("uuid") String documentCaseId,
ModelMap model,
HttpSession httpSession,
@@ -78,10 +232,58 @@ public class PunchingController extends AbstractAuthenticatedController {
return authorization.viewName();
}
Session session = authorization.session();
model.addAttribute("model", punchingService.editCase(
portfolioId, documentCaseId, session.getBranchID(), session.getUserID()));
model.addAttribute("Sessvals", session);
UserSession session = authorization.session();
model.addAttribute("model", punchingService.prepareApplicationEdit(
portfolioId, documentCaseId, session.getBranchId(),
session.getCompanyId(), session.getUserId()));
return "edp/punching/initcase";
}
@RequestMapping(value = EDIT_GRID_ROUTE, method = RequestMethod.POST)
public String openEditGrid(
ModelMap model,
HttpSession httpSession,
HttpServletResponse response) {
PageAuthorization authorization = authorizePage(
EDIT_GRID_ROUTE, model, httpSession, response);
if (!authorization.isGranted()) {
return authorization.viewName();
}
populateEditGrid(model, new CaseGrid(), authorization.session(), false);
return "edp/punching/editcases";
}
@RequestMapping(value = "caselist", method = RequestMethod.POST)
public String listEditableCases(
@ModelAttribute("caseGrid") CaseGrid caseGrid,
ModelMap model,
HttpSession httpSession,
HttpServletResponse response) {
PageAuthorization authorization = authorizePage(
EDIT_GRID_ROUTE, model, httpSession, response);
if (!authorization.isGranted()) {
return authorization.viewName();
}
populateEditGrid(model, caseGrid, authorization.session(), true);
return "edp/punching/editcases";
}
private void populateEditGrid(
ModelMap model, CaseGrid caseGrid, UserSession session, boolean loadCases) {
Short portfolioId = selectedPortfolio(caseGrid);
model.addAttribute("caseGrid", caseGrid);
model.addAttribute("portlist", punchingService.loadEditCasePortfolios(session));
model.addAttribute("caseList", loadCases && portfolioId != null
? punchingService.loadEditableCases(portfolioId, session)
: java.util.List.of());
}
private Short selectedPortfolio(CaseGrid caseGrid) {
try {
short portfolioId = Short.parseShort(caseGrid.getPortfolioId());
return portfolioId > 0 ? portfolioId : null;
} catch (NumberFormatException | NullPointerException ignored) {
return null;
}
}
}

View File

@@ -1,10 +1,6 @@
package matrix.nimble.edp.punching.model;
import matrix.nimble.utilities.DBFunctions;
import matrix.nimble.utilities.GlobalClass;
import matrix.nimble.utilities.StringFunctions;
public class CaseGrid {
public class CaseGrid {
private String ErrMsg;
private String ErrDesc;
private String ErrCode;
@@ -48,23 +44,4 @@ public class CaseGrid {
public void setCaseID(String caseID) {
CaseID = caseID;
}
public String[][] FillCaseList(String PortfolioID,String CompBranchId)
{
String [][]CaseList=null;
DBFunctions DBF=new DBFunctions(getErrCode());
DBF.setProcessFlag(true);
String ResultData=DBF.FetchRunQuery(23, (PortfolioID+GlobalClass.ColDelim+CompBranchId+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
if(DBF.isProcessFlag())
{
setProcessFlag(DBF.isProcessFlag());
CaseList=new StringFunctions(getErrCode()).ConverTo2DArray(ResultData, GlobalClass.RowDelim, GlobalClass.ColDelim);
}
else
{
setProcessFlag(false);
setErrMsg(DBF.getErrMsg());
setErrDesc(DBF.getErrDesc());
}
return CaseList;
}
}
}

View File

@@ -1,88 +0,0 @@
package matrix.nimble.edp.punching.model;
public class DocDetails {
private String portfolioid;
private String bankbranchid;
private String applno;
private String customername;
private String product;
private String apptype;
private String category;
private String loanamount;
private String dob;
private String caseid;
private String uuid;
private int formmode;
public String getPortfolioid() {
return portfolioid;
}
public void setPortfolioid(String portfolioid) {
this.portfolioid = portfolioid;
}
public String getBankbranchid() {
return bankbranchid;
}
public void setBankbranchid(String bankbranchid) {
this.bankbranchid = bankbranchid;
}
public String getApplno() {
return applno;
}
public void setApplno(String applno) {
this.applno = applno;
}
public String getCustomername() {
return customername;
}
public void setCustomername(String customername) {
this.customername = customername;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
public String getApptype() {
return apptype;
}
public void setApptype(String apptype) {
this.apptype = apptype;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getLoanamount() {
return loanamount;
}
public void setLoanamount(String loanamount) {
this.loanamount = loanamount;
}
public String getDob() {
return dob;
}
public void setDob(String dob) {
this.dob = dob;
}
public String getCaseid() {
return caseid;
}
public void setCaseid(String caseid) {
this.caseid = caseid;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public int getFormmode() {
return formmode;
}
public void setFormmode(int formmode) {
this.formmode = formmode;
}
}

View File

@@ -1,13 +1,6 @@
package matrix.nimble.edp.punching.model;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.collections.FactoryUtils;
import org.apache.commons.collections.list.LazyList;
import matrix.nimble.edp.cutoff.model.CutOffRecord;
import matrix.nimble.utilities.CommonFunctions;
import matrix.nimble.utilities.CommonFunctions;
import matrix.nimble.utilities.DBFunctions;
import matrix.nimble.utilities.GlobalClass;
import matrix.nimble.utilities.StringFunctions;
@@ -21,8 +14,6 @@ public class PunchingHandler {
private String dynamicpanel;
private String dynamicsection;
private String dynamicfields;
private String docdynamicfields;
private String docdynamicpanel;
private String portfolioid;
private String [][] optionvals;
@@ -62,18 +53,6 @@ public class PunchingHandler {
public void setDynamicpanel(String dynamicpanel) {
this.dynamicpanel = dynamicpanel;
}
public String getDocdynamicfields() {
return docdynamicfields;
}
public void setDocdynamicfields(String docdynamicfields) {
this.docdynamicfields = docdynamicfields;
}
public String getDocdynamicpanel() {
return docdynamicpanel;
}
public void setDocdynamicpanel(String docdynamicpanel) {
this.docdynamicpanel = docdynamicpanel;
}
public String getDynamicsection() {
return dynamicsection;
}
@@ -119,70 +98,6 @@ public class PunchingHandler {
setOptionvals(null);
}
}
public void DocDynamicHtml()
{
DBFunctions dbf=new DBFunctions(getErrCode());
dbf.setProcessFlag(true);
setDynamicfields("");
setDynamicpanel("");
setDocdynamicfields("");
setDocdynamicpanel("");
dbf.FetchRunQuery(74, (getPortfolioid()+GlobalClass.ColDelim+"75"+GlobalClass.ColDelim+"ADDDOC"+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
if(dbf.isProcessFlag())
{
CommonFunctions Cfunc=new CommonFunctions();
String [][] ResultSet=dbf.getResultArray();
if(ResultSet.length > 0)
{
Cfunc.setGeneratedHtml("");
Cfunc.setPrevControl("");
Cfunc.setDynamicCtrls("");
for(int indx=0;indx<ResultSet.length;indx++)
{
String ControlVal="";
String secContainer="";
String Temp="";
secContainer=Cfunc.DynamicControls(ResultSet[indx], ControlVal);
if(secContainer.equals("Generalsec"))
{
Temp=getDynamicpanel();
setDynamicfields(getDynamicfields()+ResultSet[indx][2]+GlobalClass.ColDelim);
if(Temp.endsWith("</select></div></div></div>") && Cfunc.getGeneratedHtml().endsWith("</select></div></div></div>"))
{
if(!Cfunc.getGeneratedHtml().startsWith("<div class='widget'>"))
{
Temp=Temp.substring(0,Temp.lastIndexOf("</select></div></div></div>"));
}
}
setDynamicpanel(Temp+""+Cfunc.getGeneratedHtml());
}
if(secContainer.equals("Docsec"))
{
Temp=getDocdynamicpanel();
setDocdynamicfields(getDocdynamicfields()+ResultSet[indx][2]+GlobalClass.ColDelim);
if(Temp.endsWith("</select></div></div></div>") && Cfunc.getGeneratedHtml().endsWith("</select></div></div></div>"))
{
if(!Cfunc.getGeneratedHtml().startsWith("<div class='widget'>"))
{
Temp=Temp.substring(0,Temp.lastIndexOf("</select></div></div></div>"));
}
}
setDocdynamicpanel(Temp+""+Cfunc.getGeneratedHtml());
}
}
}
else
{
setProcessFlag(false);
setErrMsg(dbf.getErrMsg());
setErrDesc(dbf.getErrDesc());
}
}
}
public void DynamicHtml(String pageId)
{
DBFunctions dbf=new DBFunctions(getErrCode());
@@ -242,11 +157,6 @@ public class PunchingHandler {
setErrDesc(dbf.getErrDesc());
}
}
public void AddEditDocs(String docType,String docHolder,String serviceProvider,String uniqueNo,String bankId,String yearMonth,String city,String vendorId,String uuId,String userId)
{
}
public String[][] loadCasesForAddrCorrection() {
String [][]resultArray = null;
DBFunctions dbf=new DBFunctions(getErrCode());

View File

@@ -14,4 +14,10 @@ public final class CloudQueryDefinitionProvider implements QueryDefinitionProvid
public QueryDefinition get(int queryId) {
return QueryDefinition.parse(queryId, provider.getQuery(queryId));
}
@Override
public QueryDefinition get(String queryKey) {
int diagnosticId = Math.max(1, queryKey.hashCode() & Integer.MAX_VALUE);
return QueryDefinition.parse(diagnosticId, provider.getQuery(queryKey));
}
}

View File

@@ -19,4 +19,11 @@ public final class CloudQuerySource implements QuerySource {
.orElseThrow(() -> new QueryProviderException(
"Cloud query was empty: " + queryId));
}
@Override
public String fetch(String queryKey) {
return client.fetchQuery(queryKey).map(response -> response.query()).blockOptional()
.filter(query -> !query.isBlank())
.orElseThrow(() -> new QueryProviderException("Cloud query was empty: " + queryKey));
}
}

View File

@@ -0,0 +1,21 @@
package matrix.nimble.query;
import java.util.Objects;
public final class DirectQueryProvider implements QueryProvider {
private final QuerySource source;
public DirectQueryProvider(QuerySource source) {
this.source = Objects.requireNonNull(source, "source");
}
@Override
public String getQuery(int queryId) {
return source.fetch(queryId);
}
@Override
public String getQuery(String queryKey) {
return source.fetch(queryKey);
}
}

View File

@@ -1,6 +1,10 @@
package matrix.nimble.query;
@FunctionalInterface
public interface QueryProvider {
String getQuery(int queryId);
default String getQuery(String queryKey) {
throw new UnsupportedOperationException("Query keys are not supported by this provider");
}
}

View File

@@ -23,12 +23,14 @@ public class QueryProviderConfiguration implements DisposableBean {
OnPremRedisCacheService cache,
CloudIdentityClient cloudClient,
CloudClientProperties cloudProperties,
@Value("${CYGNUS_QUERY_CACHE_ENABLED:true}") boolean cacheEnabled,
@Value("${CYGNUS_QUERY_CACHE_AES_KEY:}") String configuredKey) {
byte[] key = queryCacheKey(configuredKey, cloudProperties.clientAssertion());
installed = new RedisCachingQueryProvider(
cache,
new CloudQuerySource(cloudClient),
new AesGcmQueryCipher(key));
QuerySource cloudSource = new CloudQuerySource(cloudClient);
installed = cacheEnabled
? new RedisCachingQueryProvider(
cache, cloudSource, new AesGcmQueryCipher(
queryCacheKey(configuredKey, cloudProperties.clientAssertion())))
: new DirectQueryProvider(cloudSource);
QueryProviders.install(installed);
return installed;
}

View File

@@ -4,4 +4,7 @@ package matrix.nimble.query;
public interface QuerySource {
String fetch(int queryId);
default String fetch(String queryKey) {
throw new UnsupportedOperationException("Query keys are not supported by this source");
}
}

View File

@@ -30,7 +30,18 @@ public final class RedisCachingQueryProvider implements QueryProvider {
@Override
public String getQuery(int queryId) {
String cacheKey = cacheKey(queryId);
return get("id:" + cacheKey(queryId), () -> cloudSource.fetch(queryId));
}
@Override
public String getQuery(String queryKey) {
if (queryKey == null || !queryKey.matches("[A-Z][A-Z0-9_]{2,99}")) {
throw new IllegalArgumentException("Invalid query key");
}
return get("key:" + queryKey, () -> cloudSource.fetch(queryKey));
}
private String get(String cacheKey, java.util.function.Supplier<String> source) {
Optional<String> cached = cached(cacheKey);
if (cached.isPresent()) {
return cached.get();
@@ -42,14 +53,14 @@ public final class RedisCachingQueryProvider implements QueryProvider {
return cached.get();
}
try {
String query = cloudSource.fetch(queryId);
String query = source.get();
cache.put(cacheKey, cipher.encrypt(cacheKey, query), QUERY_TTL);
return query;
} catch (QueryProviderException exception) {
throw exception;
} catch (RuntimeException exception) {
throw new QueryProviderException(
"Unable to retrieve query: " + queryId, exception);
"Unable to retrieve query: " + cacheKey, exception);
}
}
}

View File

@@ -0,0 +1,174 @@
package matrix.nimble.security;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.security.spec.MGF1ParameterSpec;
import java.time.Duration;
import java.time.Instant;
import java.time.format.DateTimeParseException;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import javax.crypto.spec.SecretKeySpec;
import lib.constants.ApplicationMessage;
import lib.exceptions.ApplicationException;
import lib.models.CaseSaveRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/** Thread-safe decryption for short-lived form envelopes created with Web Crypto. */
@Service
public final class PayloadCryptoService {
private static final Duration REQUEST_TTL = Duration.ofMinutes(5);
private static final int GCM_TAG_BITS = 128;
private final ObjectMapper objectMapper;
private final PrivateKey privateKey;
private final PublicKey publicKey;
private final String keyId;
private final Map<String, Instant> acceptedRequests = new ConcurrentHashMap<>();
public PayloadCryptoService(
ObjectMapper objectMapper,
@Value("${CYGNUS_PAYLOAD_PRIVATE_KEY:${CYGNUS_CASE_SAVE_PRIVATE_KEY:}}") String privateKeyLocation,
@Value("${CYGNUS_PAYLOAD_PUBLIC_KEY:${CYGNUS_CASE_SAVE_PUBLIC_KEY:}}") String publicKeyLocation) {
this.objectMapper = objectMapper;
KeyPair pair = loadOrGenerate(privateKeyLocation, publicKeyLocation);
this.privateKey = pair.getPrivate();
this.publicKey = pair.getPublic();
this.keyId = fingerprint(publicKey);
}
public String keyId() { return keyId; }
public String encodedPublicKey() {
return Base64.getUrlEncoder().withoutPadding().encodeToString(publicKey.getEncoded());
}
public <T> T decrypt(CaseSaveRequest request, Class<T> payloadType) {
validateEnvelope(request);
Instant now = Instant.now();
Instant submittedAt;
try {
submittedAt = Instant.parse(request.timestamp());
} catch (DateTimeParseException exception) {
throw invalid("Invalid request timestamp", exception);
}
if (submittedAt.isBefore(now.minus(REQUEST_TTL))
|| submittedAt.isAfter(now.plusSeconds(30))) {
throw invalid("Expired request payload");
}
discardExpired(now);
if (acceptedRequests.putIfAbsent(request.requestId(), now) != null) {
throw invalid("Duplicate request payload");
}
try {
Base64.Decoder decoder = Base64.getUrlDecoder();
Cipher keyCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
keyCipher.init(Cipher.DECRYPT_MODE, privateKey,
new OAEPParameterSpec("SHA-256", "MGF1",
MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));
byte[] aesKey = keyCipher.doFinal(decoder.decode(request.encryptedKey()));
byte[] iv = decoder.decode(request.initializationVector());
if (iv.length != 12) throw invalid("Invalid initialization vector");
Cipher payloadCipher = Cipher.getInstance("AES/GCM/NoPadding");
payloadCipher.init(Cipher.DECRYPT_MODE,
new SecretKeySpec(aesKey, "AES"), new GCMParameterSpec(GCM_TAG_BITS, iv));
payloadCipher.updateAAD(aad(request));
byte[] json = payloadCipher.doFinal(decoder.decode(request.encryptedPayload()));
return objectMapper.readValue(json, payloadType);
} catch (ApplicationException exception) {
throw exception;
} catch (Exception exception) {
acceptedRequests.remove(request.requestId());
throw invalid("Unable to decrypt payload", exception);
}
}
private byte[] aad(CaseSaveRequest request) {
return String.join("|", request.keyId(), request.requestId(), request.timestamp())
.getBytes(StandardCharsets.UTF_8);
}
private void validateEnvelope(CaseSaveRequest request) {
if (request == null || blank(request.keyId()) || blank(request.encryptedKey())
|| blank(request.initializationVector()) || blank(request.encryptedPayload())
|| blank(request.requestId()) || blank(request.timestamp())) {
throw invalid("Incomplete encrypted request");
}
if (!keyId.equals(request.keyId())) throw invalid("Unsupported encryption key");
}
private void discardExpired(Instant now) {
Instant cutoff = now.minus(REQUEST_TTL);
acceptedRequests.entrySet().removeIf(entry -> entry.getValue().isBefore(cutoff));
}
private KeyPair loadOrGenerate(String privateLocation, String publicLocation) {
if (blank(privateLocation) && blank(publicLocation)) {
try {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(3072);
return generator.generateKeyPair();
} catch (Exception exception) {
throw new IllegalStateException("Unable to generate payload key pair", exception);
}
}
if (blank(privateLocation) || blank(publicLocation)) {
throw new IllegalStateException(
"Both CYGNUS_PAYLOAD_PRIVATE_KEY and CYGNUS_PAYLOAD_PUBLIC_KEY are required");
}
try {
KeyFactory factory = KeyFactory.getInstance("RSA");
return new KeyPair(
factory.generatePublic(new X509EncodedKeySpec(pem(publicLocation, "PUBLIC KEY"))),
factory.generatePrivate(new PKCS8EncodedKeySpec(pem(privateLocation, "PRIVATE KEY"))));
} catch (Exception exception) {
throw new IllegalStateException("Unable to load payload key pair", exception);
}
}
private byte[] pem(String location, String type) throws Exception {
String path = location.startsWith("file:") ? location.substring(5) : location;
String value = Files.readString(Path.of(path), StandardCharsets.US_ASCII)
.replace("-----BEGIN " + type + "-----", "")
.replace("-----END " + type + "-----", "")
.replaceAll("\\s", "");
return Base64.getDecoder().decode(value);
}
private String fingerprint(PublicKey key) {
try {
byte[] digest = MessageDigest.getInstance("SHA-256").digest(key.getEncoded());
return Base64.getUrlEncoder().withoutPadding().encodeToString(digest);
} catch (Exception exception) {
throw new IllegalStateException("Unable to identify payload key", exception);
}
}
private boolean blank(String value) { return value == null || value.isBlank(); }
private ApplicationException invalid(String technicalMessage) {
return new ApplicationException(ApplicationMessage.PAYLOAD_INVALID, technicalMessage);
}
private ApplicationException invalid(String technicalMessage, Throwable cause) {
return new ApplicationException(ApplicationMessage.PAYLOAD_INVALID, technicalMessage, cause);
}
}

View File

@@ -0,0 +1,16 @@
package matrix.nimble.security;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WebJsonConfiguration {
@Bean
ObjectMapper webObjectMapper() {
return new ObjectMapper()
.findAndRegisterModules()
.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
}
}

View File

@@ -5,10 +5,14 @@ import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CommonFunctions {
public class CommonFunctions {
private static final Pattern DYNAMIC_VALIDATION = Pattern.compile(
"(?i)validate\\s*\\(\\s*this\\s*,\\s*'([tf])'\\s*,\\s*'([^']*)");
private String ErrMsg;
private String ErrCode;
private String ErrDesc;
@@ -102,14 +106,15 @@ public class CommonFunctions {
}
return GatewayList;
}
public String DynamicControls(String [] Controls,String ControlVal)
{
public String DynamicControls(String [] Controls,String ControlVal)
{
String CtrlHtml="";
String CtrlStyle="";
String CtrlClass="";
String CtrlEvents="";
String isSelected="";
String maxLength="maxlength";
String maxLength="maxlength";
String validationAttributes=dynamicValidationAttributes(Controls[9]);
String unit="px";
setCtrlType(Controls[14]);
ControlVal=(ControlVal==null || ControlVal.equals("")) ? Controls[17] : ControlVal;
@@ -151,11 +156,11 @@ public class CommonFunctions {
CtrlHtml=CtrlHtml+"</div><div class='inputcontainer'>";
if(getCtrlType().equals("text"))
{
CtrlHtml=CtrlHtml+"<input type=\"text\" id='"+Controls[2]+"' name='"+Controls[2]+"' "+maxLength+" "+CtrlEvents+" "+CtrlStyle+" "+CtrlClass+" value=\""+ControlVal+"\" />";
CtrlHtml=CtrlHtml+"<input type=\"text\" id='"+Controls[2]+"' name='"+Controls[2]+"' "+maxLength+" "+validationAttributes+" "+CtrlEvents+" "+CtrlStyle+" "+CtrlClass+" value=\""+ControlVal+"\" />";
}
else if(getCtrlType().equals("checkbox"))
{
CtrlHtml=CtrlHtml+"<input id='"+Controls[2]+"' name='"+Controls[2]+"' "+maxLength+" "+CtrlEvents+" "+CtrlStyle+" "+CtrlClass+" value='"+ControlVal+"' />";
CtrlHtml=CtrlHtml+"<input id='"+Controls[2]+"' name='"+Controls[2]+"' "+maxLength+" "+validationAttributes+" "+CtrlEvents+" "+CtrlStyle+" "+CtrlClass+" value='"+ControlVal+"' />";
}
CtrlHtml=CtrlHtml+"</div></div>";
}
@@ -167,7 +172,7 @@ public class CommonFunctions {
}
CtrlHtml="<div class='widget'><div class='lblcontainer'>"+Controls[1];
CtrlHtml=CtrlHtml+"</div><div class='inputcontainer'>";
CtrlHtml=CtrlHtml+"<textarea id='"+Controls[2]+"' name='"+Controls[2]+"' "+maxLength+" "+CtrlEvents+" "+CtrlStyle+" "+CtrlClass+" >"+ControlVal+"</textarea>";
CtrlHtml=CtrlHtml+"<textarea id='"+Controls[2]+"' name='"+Controls[2]+"' "+maxLength+" "+validationAttributes+" "+CtrlEvents+" "+CtrlStyle+" "+CtrlClass+" >"+ControlVal+"</textarea>";
CtrlHtml=CtrlHtml+"</div></div>";
}
else if(getCtrlType().equals("select"))
@@ -194,7 +199,7 @@ public class CommonFunctions {
CtrlHtml="<div class='widget'><div class='lblcontainer'>"+Controls[1];
CtrlHtml=CtrlHtml+"</div><div class='inputcontainer'>";
CtrlHtml=CtrlHtml+"<div "+CtrlClass+" id='div"+Controls[2]+"' "+CtrlStyle+" >";
CtrlHtml=CtrlHtml+"<select id='"+Controls[2]+"' name='"+Controls[2]+"' "+CtrlEvents+" "+CtrlStyle1+" >";
CtrlHtml=CtrlHtml+"<select id='"+Controls[2]+"' name='"+Controls[2]+"' "+validationAttributes+" "+CtrlEvents+" "+CtrlStyle1+" >";
CtrlHtml=CtrlHtml+"<option value='-1' selected>NA</option>";
CtrlHtml=CtrlHtml+"<option value='"+Controls[19]+"' "+isSelected+" >"+Controls[19]+"</option></select></div></div></div>";
}
@@ -211,8 +216,18 @@ public class CommonFunctions {
setGeneratedHtml(CtrlHtml);
setDynamicCtrls(getDynamicCtrls()+Controls[2]+GlobalClass.ColDelim);
}
return Controls[4];
}
return Controls[4];
}
private String dynamicValidationAttributes(String onBlur)
{
if(onBlur==null || onBlur.isBlank()) return "";
Matcher matcher=DYNAMIC_VALIDATION.matcher(onBlur);
if(!matcher.find()) return "";
String format=matcher.group(2).trim().replaceFirst("[^A-Za-z0-9]+$", "");
return "data-validation-required='"+(matcher.group(1).equalsIgnoreCase("t") ? "true" : "false")+
"' data-validation-format='"+format+"'";
}
public String DesignControls(String ControlType,String Controlid,String TypeScript,String ValidationScript,String Style, String CssClass,String Fieldid,DBFunctions DBFunc,StringFunctions SFunc,String ControlVal)
{
String HtmlControl="";

View File

@@ -2,14 +2,14 @@ package matrix.services.commons;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lib.models.ErrorDetails;
import lib.models.MessageDetails;
import matrix.nimble.model.Session;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;
@Service
public class CommonErrorService {
public static final String ERROR_ATTRIBUTE = "errorDetails";
public static final String ERROR_ATTRIBUTE = "messageDetails";
private final CommonService commonService;
public CommonErrorService(CommonService commonService) {
@@ -20,9 +20,9 @@ public class CommonErrorService {
ModelMap model,
HttpServletResponse response,
HttpSession httpSession,
ErrorDetails errorDetails) {
response.setStatus(errorDetails.getHttpStatus());
model.addAttribute(ERROR_ATTRIBUTE, errorDetails);
MessageDetails messageDetails) {
response.setStatus(messageDetails.getHttpStatus());
model.addAttribute(ERROR_ATTRIBUTE, messageDetails);
Session session = commonService.getSession(httpSession);
if (session != null) {

View File

@@ -3,6 +3,7 @@ package matrix.services.commons;
import com.cygnus.db.CygnusDbExecutor;
import jakarta.servlet.http.HttpSession;
import lib.models.Option;
import lib.models.UserSession;
import java.util.List;
import java.util.Objects;
@@ -15,6 +16,7 @@ import org.springframework.stereotype.Service;
@Service
public class CommonService {
public static final String SESSION_ATTRIBUTE = "Sessvals";
public static final String USER_SESSION_ATTRIBUTE = "userSession";
private static final Pattern MENU_COMMAND = Pattern.compile(
"SubmitMenuCommand\\(\\s*'([^']+)'\\s*,",
@@ -46,6 +48,20 @@ public class CommonService {
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) {
return hasPageAccess(getSession(httpSession), pageRoute);
}
@@ -69,6 +85,29 @@ public class CommonService {
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) {
if (route == null) {
return "";

View File

@@ -1,19 +1,37 @@
package matrix.services.edp;
import com.cygnus.db.CygnusDbExecutor;
import com.cygnus.db.RowView;
import com.cygnus.db.SqlArrayParameter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.sql.SQLException;
import java.sql.Date;
import java.time.LocalDate;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import lib.models.ApplicationDetails;
import lib.models.CasePunching;
import lib.models.ErrorDetails;
import lib.models.ApplicationSaveResult;
import lib.models.MessageDetails;
import lib.models.Option;
import lib.constants.ApplicationError;
import lib.models.PunchedRecordsData;
import lib.models.DuplicateDetailsData;
import lib.models.EditCaseSummary;
import lib.models.LocalityData;
import lib.models.LocalityOption;
import lib.models.UserSession;
import lib.constants.ApplicationMessage;
import lib.exceptions.ApplicationException;
import matrix.nimble.edp.punching.model.PunchingHandler;
import matrix.nimble.utilities.CommonFunctions;
import matrix.nimble.utilities.GlobalClass;
import matrix.services.commons.CommonService;
@@ -25,17 +43,294 @@ public class PunchingService {
private static final String PRODUCT = "product.";
private static final String CITY = "city.";
private static final String APPLICATION_TYPE = "applicationType.";
private static final String DATABASE_APPLICATION_TYPE = "apptype.";
private static final String CATEGORY = "category.";
private static final Short ACTIVE = Short.valueOf((short) 1);
private static final int PUNCHED_RECORDS_QUERY = 24;
private static final int EDIT_CASES_QUERY = 23;
private static final int EDIT_CASE_PORTFOLIOS_QUERY = 249;
private static final int LOCALITY_QUERY = 13;
private static final int RESIDENCE_DETAILS_QUERY = 19;
private static final int OFFICE_DETAILS_QUERY = 20;
private static final int PROPERTY_DETAILS_QUERY = 21;
private static final int CO_APPLICANT_DETAILS_QUERY = 22;
private static final Pattern DYNAMIC_FIELD = Pattern.compile(
"(?:field(?:[1-9]|1[0-2]|150(?:_2)?)|dtfield1)", Pattern.CASE_INSENSITIVE);
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 CygnusDbExecutor dbExecutor;
private final ObjectMapper objectMapper;
public PunchingService(CommonService commonService) {
this.commonService = commonService;
this.dbExecutor = null;
this.objectMapper = null;
}
@Autowired
public PunchingService(
CommonService commonService, CygnusDbExecutor dbExecutor, ObjectMapper objectMapper) {
this.commonService = commonService;
this.dbExecutor = dbExecutor;
this.objectMapper = objectMapper;
}
public ApplicationSaveResult saveApplication(ApplicationDetails details, UserSession session) {
if (dbExecutor == null || objectMapper == null) {
throw new IllegalStateException("Application-save dependencies are not configured");
}
validate(details, session);
sanitizeDynamicFields(details);
try {
String json = objectMapper.writeValueAsString(details);
ApplicationSaveResult result = dbExecutor.procedure("APPLICATION_SAVE",
new Object[] {json, session.getCompanyId(), session.getBranchId(),
session.getUserId()}, ApplicationSaveResult.class);
if (result == null || result.getApplicationId() == null) {
throw new ApplicationException(
ApplicationMessage.APPLICATION_SAVE_FAILED, "Database returned no application result");
}
return result;
} catch (JsonProcessingException exception) {
throw new ApplicationException(
ApplicationMessage.PAYLOAD_INVALID, "Unable to serialize application details", exception);
} catch (ApplicationException exception) {
throw exception;
} catch (RuntimeException exception) {
throw databaseFailure(exception);
}
}
public List<Option> loadEditCasePortfolios(UserSession session) {
requireSessionScope(session);
return commonService.getOptions(EDIT_CASE_PORTFOLIOS_QUERY, new Object[] {
session.getCompanyId(), session.getBranchId(), session.getUserId(),
session.getUserId(), ACTIVE
});
}
public List<EditCaseSummary> loadEditableCases(Short portfolioId, UserSession session) {
requireSessionScope(session);
if (portfolioId == null || portfolioId <= 0) {
throw new ApplicationException(
ApplicationMessage.APPLICATION_VALIDATION_FAILED, "Portfolio is required");
}
try {
return dbExecutor.query(EDIT_CASES_QUERY, new Object[] {
portfolioId, session.getCompanyId(), session.getBranchId()
}, EditCaseSummary.class);
} catch (RuntimeException exception) {
throw databaseFailure(exception);
}
}
private void requireSessionScope(UserSession session) {
if (session == null || session.getCompanyId() == null || session.getBranchId() == null
|| session.getUserId() == null) {
throw new ApplicationException(
ApplicationMessage.SESSION_REQUIRED, "Authenticated session scope is required");
}
if (dbExecutor == null) {
throw new IllegalStateException("Database dependencies are not configured");
}
}
public PunchedRecordsData loadPunchedRecords(
Short portfolioId, String documentCaseId, UserSession session) {
if (dbExecutor == null || objectMapper == null) {
throw new IllegalStateException("Punched-record dependencies are not configured");
}
if (portfolioId == null || portfolioId <= 0 || session == null) {
throw new ApplicationException(
ApplicationMessage.APPLICATION_VALIDATION_FAILED, "Portfolio is required");
}
String caseUuid = documentCaseId != null && documentCaseId.trim().length() > 20
? documentCaseId.trim() : "";
try {
List<RowView> rows = dbExecutor.query(PUNCHED_RECORDS_QUERY, new Object[] {
caseUuid, caseUuid, caseUuid, portfolioId,
session.getCompanyId(), session.getBranchId()
});
return new PunchedRecordsData(rows.stream().map(this::toPunchedRecord).toList());
} catch (ApplicationException exception) {
throw exception;
} catch (RuntimeException exception) {
throw databaseReadFailure(exception);
}
}
public DuplicateDetailsData findDuplicateDetails(
String applicationNumber, Short portfolioId, Integer queryId, UserSession session) {
if (dbExecutor == null) {
throw new IllegalStateException("Duplicate-detail dependencies are not configured");
}
if (blank(applicationNumber) || portfolioId == null || portfolioId <= 0
|| queryId == null || session == null) {
throw new ApplicationException(
ApplicationMessage.APPLICATION_VALIDATION_FAILED, "Duplicate search details are invalid");
}
Date receivedDate = Date.valueOf(LocalDate.now());
Object[] parameters = switch (queryId) {
case RESIDENCE_DETAILS_QUERY, OFFICE_DETAILS_QUERY, CO_APPLICANT_DETAILS_QUERY ->
new Object[] {applicationNumber.trim(), portfolioId, receivedDate,
session.getCompanyId(), session.getBranchId()};
case PROPERTY_DETAILS_QUERY ->
new Object[] {applicationNumber.trim(), portfolioId,
session.getCompanyId(), session.getBranchId(), receivedDate};
default -> throw new ApplicationException(
ApplicationMessage.APPLICATION_VALIDATION_FAILED, "Unsupported duplicate search type");
};
try {
List<Map<String, Object>> records = dbExecutor.query(queryId, parameters).stream()
.map(row -> {
Map<String, Object> record = new LinkedHashMap<>();
row.asMap().forEach((name, value) -> record.put(name, value == null ? "" : value));
return record;
})
.toList();
return new DuplicateDetailsData(records);
} catch (ApplicationException exception) {
throw exception;
} catch (RuntimeException exception) {
throw databaseFailure(exception);
}
}
public LocalityData findLocalities(String city, String letters, UserSession session) {
if (dbExecutor == null) {
throw new IllegalStateException("Locality dependencies are not configured");
}
String normalizedCity = city == null ? "-1" : city.trim();
String prefix = letters == null ? "" : letters.trim();
if (session == null || session.getBranchId() == null || prefix.isEmpty()
|| prefix.length() > 50 || normalizedCity.length() > 100) {
throw new ApplicationException(
ApplicationMessage.APPLICATION_VALIDATION_FAILED, "Locality search details are invalid");
}
try {
List<LocalityOption> localities = dbExecutor.query(LOCALITY_QUERY, new Object[] {
session.getBranchId(), prefix, normalizedCity, normalizedCity
}).stream().map(row -> new LocalityOption(
row.get("id", Integer.class), rowText(row, "location"),
rowText(row, "pincode").trim(), rowText(row, "city"))).toList();
return new LocalityData(localities);
} catch (ApplicationException exception) {
throw exception;
} catch (RuntimeException exception) {
throw new ApplicationException(
ApplicationMessage.INTERNAL_SERVER_ERROR, "Locality lookup failed", exception);
}
}
private String rowText(RowView row, String column) {
Object value = row.get(column);
return value == null ? "" : value.toString();
}
private Map<String, Object> toPunchedRecord(RowView row) {
Map<String, Object> record = new LinkedHashMap<>();
row.asMap().forEach((name, value) -> {
if (!"dynamic_fields".equalsIgnoreCase(name)) record.put(name, value == null ? "" : value);
});
Object dynamicValue = row.get("dynamic_fields");
if (dynamicValue == null || dynamicValue.toString().isBlank()) return record;
try {
Map<String, Object> dynamicFields = objectMapper.readValue(
dynamicValue.toString(), new TypeReference<Map<String, Object>>() {});
dynamicFields.forEach((name, value) -> {
if (name != null && DYNAMIC_FIELD.matcher(name).matches()) {
record.put(name, value == null ? "" : value);
}
});
return record;
} catch (JsonProcessingException exception) {
throw new ApplicationException(
ApplicationMessage.INTERNAL_SERVER_ERROR,
"Punched-record dynamic fields are invalid", exception);
}
}
private void validate(ApplicationDetails details, UserSession session) {
if (details == null || session == null || details.getPortfolioId() == null
|| details.getPortfolioId() <= 0) {
throw new ApplicationException(
ApplicationMessage.APPLICATION_VALIDATION_FAILED, "Portfolio is required");
}
if (details.getBankBranchId() == null || details.getBankBranchId() <= 0) {
throw new ApplicationException(
ApplicationMessage.APPLICATION_VALIDATION_FAILED, "Bank branch is required");
}
if (blank(details.getApplicationNumber()) || blank(details.getProduct())
|| blank(details.getCustomerName()) || blank(details.getApplicationType())) {
throw new ApplicationException(
ApplicationMessage.APPLICATION_VALIDATION_FAILED, "Required application fields are missing");
}
if (!Boolean.TRUE.equals(details.getResidenceVerification())
&& !Boolean.TRUE.equals(details.getResidenceTelephoneVerification())
&& !Boolean.TRUE.equals(details.getOfficeVerification())
&& !Boolean.TRUE.equals(details.getOfficeTelephoneVerification())
&& !Boolean.TRUE.equals(details.getPropertyVerification())
&& !Boolean.TRUE.equals(details.getReferenceVerification())
&& !Boolean.TRUE.equals(details.getDocumentVerification())) {
throw new ApplicationException(
ApplicationMessage.APPLICATION_VALIDATION_FAILED,
"At least one verification type is required");
}
}
private void sanitizeDynamicFields(ApplicationDetails details) {
if (details.getDynamicFields() == null || details.getDynamicFields().isEmpty()) {
details.setDynamicFields(new LinkedHashMap<>());
return;
}
Map<String, String> allowed = new LinkedHashMap<>();
details.getDynamicFields().forEach((name, value) -> {
if (name != null && DYNAMIC_FIELD.matcher(name).matches()) {
allowed.put(name, value == null ? null : value.trim());
}
});
details.setDynamicFields(allowed);
}
private ApplicationException databaseFailure(RuntimeException exception) {
Throwable cause = exception;
while (cause != null) {
if (cause instanceof SQLException sqlException) {
return switch (sqlException.getSQLState()) {
case "42501" -> new ApplicationException(
ApplicationMessage.APPLICATION_ACCESS_DENIED, sqlException.getMessage(), exception);
case "22023", "23502", "23503" -> new ApplicationException(
ApplicationMessage.APPLICATION_VALIDATION_FAILED, sqlException.getMessage(), exception);
case "23505" -> new ApplicationException(
ApplicationMessage.APPLICATION_SAVE_CONFLICT, sqlException.getMessage(), exception);
default -> new ApplicationException(
ApplicationMessage.APPLICATION_SAVE_FAILED, "Database save failed", exception);
};
}
cause = cause.getCause();
}
return new ApplicationException(
ApplicationMessage.APPLICATION_SAVE_FAILED, "Database save failed", exception);
}
private ApplicationException databaseReadFailure(RuntimeException exception) {
return new ApplicationException(
ApplicationMessage.APPLICATION_LOAD_FAILED,
"Database read failed", exception);
}
private boolean blank(String value) { return value == null || value.isBlank(); }
public CasePunching init(
String branchId,
String userId,
Short branchId,
Short userId,
String verificationCaseId,
String documentCaseId) {
PunchingHandler punchingHandler = new PunchingHandler();
@@ -43,16 +338,15 @@ public class PunchingService {
CasePunching casePunching = new CasePunching();
Map<String, List<Option>> options = new LinkedHashMap<>();
Short databaseBranchId = Short.valueOf(branchId.trim());
List<Option> portfolios = commonService.getOptions(
3, new Object[] { databaseBranchId, Short.valueOf((short) 1) });
3, new Object[] { branchId, ACTIVE });
addOptions(options, PORTFOLIO, portfolios);
casePunching.setOptions(Collections.unmodifiableMap(options));
casePunching.setOptions(freezeOptions(options));
casePunching.setVisibleSections(List.of());
casePunching.setPortfolioId(-1);
casePunching.setPortfolioId((short) -1);
casePunching.setFormMode(0);
casePunching.setUserId(userId);
casePunching.setUserId(Short.toString(userId));
casePunching.setDynamicFields("");
casePunching.setDynamicHtml("");
casePunching.setVerificationCaseId(verificationCaseId);
@@ -60,31 +354,31 @@ public class PunchingService {
return casePunching;
}
public CasePunching addCase(
public CasePunching prepareNewApplication(
CasePunching submitted,
String branchIds,
String userId) {
Short branchId,
Short companyId,
Short userId) {
CasePunching result = new CasePunching();
result.setPortfolioId(submitted.getPortfolioId());
result.setFormMode(1);
result.setUserId(userId);
result.setUserId(Short.toString(userId));
result.setVerificationCaseId(submitted.getVerificationCaseId());
result.setDocumentCaseId("xxx");
if (submitted.getPortfolioId() == null || submitted.getPortfolioId() <= 0) {
result.setOptions(Collections.emptyMap());
result.setOptions(Map.of());
result.setVisibleSections(List.of());
result.setDynamicFields("");
result.setDynamicHtml("");
result.setErrorDetails(new ErrorDetails(ApplicationError.BAD_REQUEST));
result.setMessageDetails(new MessageDetails(ApplicationMessage.BAD_REQUEST));
return result;
}
String portfolioId = submitted.getPortfolioId().toString();
Short portfolioId = submitted.getPortfolioId();
PunchingHandler punchingHandler = new PunchingHandler();
CommonFunctions commonFunctions = new CommonFunctions();
punchingHandler.setErrCode("1001");
punchingHandler.setPortfolioid(portfolioId);
punchingHandler.setPortfolioid(Short.toString(portfolioId));
punchingHandler.setProcessFlag(true);
punchingHandler.DynamicHtml("10");
@@ -98,68 +392,43 @@ public class PunchingService {
result.setDynamicFields("");
result.setDynamicHtml("");
result.setVisibleSections(List.of());
result.setErrorDetails(new ErrorDetails(ApplicationError.INTERNAL_SERVER_ERROR));
result.setMessageDetails(new MessageDetails(ApplicationMessage.INTERNAL_SERVER_ERROR));
}
Map<String, String> options = new LinkedHashMap<>();
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));
result.setOptions(loadOptions(branchId, companyId, portfolioId));
return result;
}
public CasePunching editCase(
Integer portfolioId,
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 prepareApplicationEdit(
Short portfolioId,
String documentCaseId,
String branchIds,
String userId) {
Short branchId,
Short companyId,
Short userId) {
CasePunching submitted = new CasePunching();
submitted.setPortfolioId(portfolioId);
submitted.setDocumentCaseId(documentCaseId);
CasePunching result = addCase(submitted, branchIds, userId);
CasePunching result = prepareNewApplication(submitted, branchId, companyId, userId);
result.setFormMode(2);
result.setDocumentCaseId(documentCaseId);
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) {
if (values == null || values.isEmpty()) {
return;
@@ -178,6 +447,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) {
if (sections == null || sections.isBlank()) {
return List.of();

View File

@@ -310,7 +310,8 @@ class RoleVisibleBatchMigrationTest {
Path.of("build/WebContent/WEB-INF/app/operation/tools").resolve(page));
assertTrue(content.contains("matrix-shell matrix-tool-workspace"), 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("centerDivBoth(\"formcontainer\""), page);
}
@@ -501,34 +502,22 @@ class RoleVisibleBatchMigrationTest {
assertFalse(documents.contains("z-index:-1"));
Path punching = Path.of("build/WebContent/WEB-INF/app/edp/punching");
for (String page : List.of("addcases.jsp", "initcase.jsp", "initdocs.jsp")) {
for (String page : List.of("initcase.jsp")) {
String content = Files.readString(punching.resolve(page));
assertTrue(content.contains("matrix-tool-workspace matrix-punch-workspace"), 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("centerDivBoth(\"formcontainer\""), page);
}
String addCases = Files.readString(punching.resolve("addcases.jsp"));
assertTrue(addCases.contains("ValidateSubmitForm('caseDetails')"));
assertTrue(addCases.contains("FindSameDet(this,'R','ResiPhone')"));
assertTrue(addCases.contains("matrix-dialog-child.js"));
assertTrue(addCases.contains("MatrixDialog.close(0)"));
assertTrue(addCases.contains("MatrixDialog.close(1)"));
assertFalse(addCases.contains("window.returnValue"));
assertFalse(addCases.contains("window.close()"));
String initialCase = Files.readString(punching.resolve("initcase.jsp"));
assertTrue(initialCase.contains("GotoRecord(this,'recno')"));
assertTrue(initialCase.contains("ValidateSubmitForm('casedetails')"));
assertTrue(initialCase.contains("CygnusInitiation.save(event)"));
assertTrue(initialCase.contains("/matrix/js/edp/punching/initiation.js"));
assertTrue(initialCase.contains("AddNewRecord()"));
String initialDocs = Files.readString(punching.resolve("initdocs.jsp"));
assertTrue(initialDocs.contains("EditBasicDetails()"));
assertTrue(initialDocs.contains("AddDocs()"));
assertTrue(initialDocs.contains("AddNewDoc()"));
String editCases = Files.readString(punching.resolve("editcases.jsp"));
assertTrue(editCases.contains("matrix-tool-workspace"));
assertTrue(editCases.contains("SubmitForm('caselist','_parent','caseGrid')"));
@@ -551,7 +540,7 @@ class RoleVisibleBatchMigrationTest {
assertTrue(workspace.contains("left: auto !important"));
Path punching = Path.of("build/WebContent/WEB-INF/app/edp/punching");
for (String page : List.of("addcases.jsp", "initcase.jsp", "initdocs.jsp")) {
for (String page : List.of("initcase.jsp")) {
String content = Files.readString(punching.resolve(page));
assertTrue(content.contains("matrix-add-cases"), page);
assertTrue(content.contains("add-cases-v4.css"), page);

View File

@@ -5,11 +5,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.lang.reflect.Method;
import jakarta.servlet.http.HttpSession;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.stereotype.Controller;
import matrix.nimble.controller.Ajax;
import matrix.nimble.edp.punching.controllers.PunchingController;
class SpringWebContextTest {
@@ -33,8 +34,8 @@ class SpringWebContextTest {
@Test
void requestParameterNamesAreRetained() throws Exception {
Method method = Ajax.class.getMethod(
"PunchedRecords", String.class, String.class, String.class);
Method method = PunchingController.class.getMethod(
"punchedRecords", Short.class, String.class, HttpSession.class);
assertTrue(method.getParameters()[0].isNamePresent());
assertTrue(method.getParameters()[1].isNamePresent());

View File

@@ -8,13 +8,13 @@ import com.cygnus.client.model.CloudIdentitySession;
import com.cygnus.client.model.CloudMenuItem;
import java.time.Instant;
import java.util.List;
import matrix.nimble.model.Session;
import lib.models.UserSession;
import org.junit.jupiter.api.Test;
class CloudSessionMapperTest {
@Test
void mapsCloudIdentityAndStructuredMenuToLegacySession() {
void mapsCloudIdentityAndStructuredMenuToTypedSession() {
CloudIdentitySession identity = new CloudIdentitySession(
(short) 17,
"maddy",
@@ -37,9 +37,9 @@ class CloudSessionMapperTest {
(short) 11, "Scanning", "scanreporting", (short) 10,
(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("Operations", session.getUserGroupName());
assertEquals("Mayapuri", session.getBranchName());
@@ -49,4 +49,19 @@ class CloudSessionMapperTest {
assertTrue(session.getMenuHtml().contains("Scanning"));
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.assertTrue;
import matrix.nimble.model.Session;
import lib.models.UserSession;
import matrix.services.commons.CommonErrorService;
import matrix.services.commons.CommonService;
import org.junit.jupiter.api.Test;
@@ -20,8 +20,8 @@ class AbstractAuthenticatedControllerTest {
@Test
void grantsAConfiguredMenuRoute() {
MockHttpSession httpSession = new MockHttpSession();
Session session = sessionWithRoute("initview");
commonService.storeSession(httpSession, session);
UserSession session = sessionWithRoute("initview");
commonService.storeUserSession(httpSession, session);
AbstractAuthenticatedController.PageAuthorization result = controller.authorize(
"initview", new ModelMap(), httpSession, new MockHttpServletResponse());
@@ -39,7 +39,7 @@ class AbstractAuthenticatedControllerTest {
assertEquals(401, noSessionResponse.getStatus());
MockHttpSession httpSession = new MockHttpSession();
commonService.storeSession(httpSession, sessionWithRoute("dashboard"));
commonService.storeUserSession(httpSession, sessionWithRoute("dashboard"));
MockHttpServletResponse deniedResponse = new MockHttpServletResponse();
AbstractAuthenticatedController.PageAuthorization denied = controller.authorize(
"initview", new ModelMap(), httpSession, deniedResponse);
@@ -47,11 +47,11 @@ class AbstractAuthenticatedControllerTest {
assertEquals(403, deniedResponse.getStatus());
}
private Session sessionWithRoute(String route) {
Session session = new Session();
session.setMenuHtml("<a onclick=\"SubmitMenuCommand('" + route
+ "','_parent','MenuForm','')\">Page</a>");
return session;
private UserSession sessionWithRoute(String route) {
return UserSession.builder()
.menuHtml("<a onclick=\"SubmitMenuCommand('" + route
+ "','_parent','MenuForm','')\">Page</a>")
.build();
}
private static final class TestController extends AbstractAuthenticatedController {

View File

@@ -0,0 +1,66 @@
package matrix.nimble.security;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.time.Instant;
import java.util.Base64;
import java.util.UUID;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import lib.models.ApplicationDetails;
import lib.models.CaseSaveRequest;
import lib.exceptions.ApplicationException;
import org.junit.jupiter.api.Test;
class PayloadCryptoServiceTest {
@Test
void decryptsBrowserCompatibleEnvelopeAndRejectsReplay() throws Exception {
ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
PayloadCryptoService service = new PayloadCryptoService(mapper, "", "");
ApplicationDetails details = new ApplicationDetails();
details.setApplicationId(42);
details.setApplicationNumber("APP-42");
String requestId = UUID.randomUUID().toString();
String timestamp = Instant.now().toString();
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(
new X509EncodedKeySpec(Base64.getUrlDecoder().decode(service.encodedPublicKey())));
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(256);
SecretKey aesKey = generator.generateKey();
byte[] iv = new byte[12];
java.security.SecureRandom.getInstanceStrong().nextBytes(iv);
byte[] aad = String.join("|", service.keyId(), requestId, timestamp)
.getBytes(StandardCharsets.UTF_8);
Cipher payload = Cipher.getInstance("AES/GCM/NoPadding");
payload.init(Cipher.ENCRYPT_MODE, aesKey, new GCMParameterSpec(128, iv));
payload.updateAAD(aad);
byte[] encryptedPayload = payload.doFinal(mapper.writeValueAsBytes(details));
Cipher wrapper = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
wrapper.init(Cipher.ENCRYPT_MODE, publicKey,
new OAEPParameterSpec("SHA-256", "MGF1",
MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));
byte[] encryptedKey = wrapper.doFinal(aesKey.getEncoded());
Base64.Encoder encoder = Base64.getUrlEncoder().withoutPadding();
CaseSaveRequest request = new CaseSaveRequest(
service.keyId(), encoder.encodeToString(encryptedKey), encoder.encodeToString(iv),
encoder.encodeToString(encryptedPayload), requestId, timestamp);
assertEquals(42, service.decrypt(request, ApplicationDetails.class).getApplicationId());
assertThrows(ApplicationException.class, () -> service.decrypt(request, ApplicationDetails.class));
}
}

Some files were not shown because too many files have changed in this diff Show More