Fixed Installer Issue

This commit is contained in:
2026-08-08 08:05:29 +05:30
parent bc00515c1b
commit b862a3f686
20 changed files with 648 additions and 104 deletions

View File

@@ -46,6 +46,10 @@ public class PunchingController extends AbstractAuthenticatedController {
private static final String DUPLICATE_DETAILS_ROUTE = "findsdet";
private static final String LOCALITY_ROUTE = "getlocality";
private static final String EDIT_GRID_ROUTE = "editgrid";
private static final String GET_PUNCHED_RECORDS = "punchedrecs";
private static final String GET_PAYLOAD_KEY = "payload-key";
private static final String SAVE_APPLICATION = "application-save";
private static final String GET_CASE_LIST = "caselist";
private final PunchingService punchingService;
private final PayloadCryptoService cryptoService;
@@ -56,20 +60,19 @@ public class PunchingController extends AbstractAuthenticatedController {
this.cryptoService = cryptoService;
}
@RequestMapping(value = "payload-key", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(value = GET_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());
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)
@RequestMapping(value = GET_PUNCHED_RECORDS, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<ApiResponse<PunchedRecordsData>> punchedRecords(
@RequestParam("portfolioId") Short portfolioId,
@@ -96,8 +99,7 @@ public class PunchingController extends AbstractAuthenticatedController {
}
}
@RequestMapping(value = DUPLICATE_DETAILS_ROUTE, method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(value = DUPLICATE_DETAILS_ROUTE, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<ApiResponse<DuplicateDetailsData>> findDuplicateDetails(
@RequestParam("applicationNumber") String applicationNumber,
@@ -125,8 +127,7 @@ public class PunchingController extends AbstractAuthenticatedController {
}
}
@RequestMapping(value = LOCALITY_ROUTE, method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(value = LOCALITY_ROUTE, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<ApiResponse<LocalityData>> findLocalities(
@RequestParam("city") String city,
@@ -152,14 +153,13 @@ public class PunchingController extends AbstractAuthenticatedController {
}
}
@RequestMapping(value = "application-save", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(value = SAVE_APPLICATION, 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());
if (!authorization.isGranted())
return applicationError(authorization.error());
try {
ApplicationDetails details = cryptoService.decrypt(request, ApplicationDetails.class);
ApplicationSaveResult saved = punchingService.saveApplication(details, authorization.session());
@@ -253,7 +253,7 @@ public class PunchingController extends AbstractAuthenticatedController {
return "edp/punching/editcases";
}
@RequestMapping(value = "caselist", method = RequestMethod.POST)
@RequestMapping(value = GET_CASE_LIST, method = RequestMethod.POST)
public String listEditableCases(
@ModelAttribute("caseGrid") CaseGrid caseGrid,
ModelMap model,

View File

@@ -31,8 +31,7 @@ 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.GlobalClass;
import matrix.nimble.utilities.CommonFunctions;
import matrix.services.commons.CommonService;
@Service
@@ -55,12 +54,14 @@ public class PunchingService {
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 int VISIBLE_SECTIONS_QUERY = 10;
private static final int DYNAMIC_CONTROLS_QUERY = 74;
private static final Short CASE_INITIATION_PAGE = Short.valueOf((short) 10);
private static final String ADD_CASE_TEMPLATE = "ADDCASE";
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 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;
@@ -89,8 +90,9 @@ public class PunchingService {
try {
String json = objectMapper.writeValueAsString(details);
ApplicationSaveResult result = dbExecutor.procedure("APPLICATION_SAVE",
new Object[] {json, session.getCompanyId(), session.getBranchId(),
session.getUserId()}, ApplicationSaveResult.class);
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");
@@ -150,7 +152,8 @@ public class PunchingService {
ApplicationMessage.APPLICATION_VALIDATION_FAILED, "Portfolio is required");
}
String caseUuid = documentCaseId != null && documentCaseId.trim().length() > 20
? documentCaseId.trim() : "";
? documentCaseId.trim()
: "";
try {
List<RowView> rows = dbExecutor.query(PUNCHED_RECORDS_QUERY, new Object[] {
caseUuid, caseUuid, caseUuid, portfolioId,
@@ -178,11 +181,11 @@ public class PunchingService {
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()};
new Object[] { applicationNumber.trim(), portfolioId, receivedDate,
session.getCompanyId(), session.getBranchId() };
case PROPERTY_DETAILS_QUERY ->
new Object[] {applicationNumber.trim(), portfolioId,
session.getCompanyId(), session.getBranchId(), receivedDate};
new Object[] { applicationNumber.trim(), portfolioId,
session.getCompanyId(), session.getBranchId(), receivedDate };
default -> throw new ApplicationException(
ApplicationMessage.APPLICATION_VALIDATION_FAILED, "Unsupported duplicate search type");
};
@@ -237,13 +240,16 @@ public class PunchingService {
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);
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;
if (dynamicValue == null || dynamicValue.toString().isBlank())
return record;
try {
Map<String, Object> dynamicFields = objectMapper.readValue(
dynamicValue.toString(), new TypeReference<Map<String, Object>>() {});
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);
@@ -326,16 +332,15 @@ public class PunchingService {
"Database read failed", exception);
}
private boolean blank(String value) { return value == null || value.isBlank(); }
private boolean blank(String value) {
return value == null || value.isBlank();
}
public CasePunching init(
Short branchId,
Short userId,
String verificationCaseId,
String documentCaseId) {
PunchingHandler punchingHandler = new PunchingHandler();
punchingHandler.setErrCode("1001");
CasePunching casePunching = new CasePunching();
Map<String, List<Option>> options = new LinkedHashMap<>();
List<Option> portfolios = commonService.getOptions(
@@ -376,41 +381,97 @@ public class PunchingService {
}
Short portfolioId = submitted.getPortfolioId();
PunchingHandler punchingHandler = new PunchingHandler();
punchingHandler.setErrCode("1001");
punchingHandler.setPortfolioid(Short.toString(portfolioId));
punchingHandler.setProcessFlag(true);
punchingHandler.DynamicHtml("10");
if (punchingHandler.isProcessFlag()) {
result.setDynamicFields(defaultString(punchingHandler.getDynamicfields()));
result.setDynamicHtml(defaultString(punchingHandler.getDynamicpanel()));
String sections = defaultString(punchingHandler.GetVisibleSections())
+ defaultString(punchingHandler.getDynamicsection());
result.setVisibleSections(toVisibleSections(sections));
} else {
result.setDynamicFields("");
result.setDynamicHtml("");
result.setVisibleSections(List.of());
result.setMessageDetails(new MessageDetails(ApplicationMessage.INTERNAL_SERVER_ERROR));
try {
DynamicContent dynamicContent = loadDynamicContent(portfolioId);
result.setDynamicFields(dynamicContent.fields());
result.setDynamicHtml(dynamicContent.html());
result.setVisibleSections(dynamicContent.visibleSections());
} catch (RuntimeException exception) {
throw databaseReadFailure(exception);
}
result.setOptions(loadOptions(branchId, companyId, portfolioId));
return result;
}
private DynamicContent loadDynamicContent(Short portfolioId) {
if (dbExecutor == null) {
throw new IllegalStateException("Database dependencies are not configured");
}
List<String> visibleSections = dbExecutor.query(
VISIBLE_SECTIONS_QUERY,
new Object[] {CASE_INITIATION_PAGE, portfolioId})
.stream()
.map(row -> rowText(row, "control").trim())
.filter(value -> !value.isEmpty())
.distinct()
.collect(java.util.stream.Collectors.toCollection(java.util.ArrayList::new));
List<RowView> controls = dbExecutor.query(
DYNAMIC_CONTROLS_QUERY,
new Object[] {portfolioId, CASE_INITIATION_PAGE, ADD_CASE_TEMPLATE});
if (controls.isEmpty()) {
return new DynamicContent("", "", List.copyOf(visibleSections));
}
CommonFunctions controlsRenderer = new CommonFunctions();
controlsRenderer.setGeneratedHtml("");
controlsRenderer.setPrevControl("");
controlsRenderer.setDynamicCtrls("");
StringBuilder html = new StringBuilder();
for (RowView row : controls) {
String container = controlsRenderer.DynamicControls(
dynamicControlValues(row), "");
if (!"Othersec".equals(container)) {
continue;
}
String generated = defaultString(controlsRenderer.getGeneratedHtml());
trimDuplicateSelectClosing(html, generated);
html.append(generated);
}
visibleSections.add("section6");
return new DynamicContent(
defaultString(controlsRenderer.getDynamicCtrls()),
html.toString(),
visibleSections.stream().distinct().toList());
}
private String[] dynamicControlValues(RowView row) {
String[] columns = {
"field_id", "label", "controlid", "cssclass", "containerid", "maxlength",
"onclick", "ondbclick", "onfocus", "onblur", "onkeypress", "onkeydown",
"onkeyup", "onchange", "ctrltype", "ctrlwidth", "ctrlheight", "defaultvalue",
"fieldorder", "fieldvalue", "valorder", "page_id", "portfolio_id",
"template_id", "template", "template_type", "isvisible"
};
String[] values = new String[columns.length];
for (int index = 0; index < columns.length; index++) {
values[index] = rowText(row, columns[index]);
}
return values;
}
private void trimDuplicateSelectClosing(StringBuilder html, String generated) {
String closing = "</select></div></div></div>";
if (html.toString().endsWith(closing)
&& generated.endsWith(closing)
&& !generated.startsWith("<div class='widget'>")) {
html.setLength(html.length() - closing.length());
}
}
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}));
3, new Object[] { branchId, ACTIVE }));
addOptions(options, BRANCH, commonService.getOptions(
4, new Object[] {portfolioId, ACTIVE}));
4, new Object[] { portfolioId, ACTIVE }));
addGroupedOptions(options, commonService.getOptions(
5, new Object[] {companyId, GENERAL_OPTION_TYPES}));
5, new Object[] { companyId, GENERAL_OPTION_TYPES }));
addGroupedOptions(options, commonService.getOptions(
70, new Object[] {portfolioId, PORTFOLIO_OPTION_TYPES}));
70, new Object[] { portfolioId, PORTFOLIO_OPTION_TYPES }));
return freezeOptions(options);
}
@@ -471,9 +532,12 @@ public class PunchingService {
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;
if (CITY.equalsIgnoreCase(normalized))
return CITY;
if (CATEGORY.equalsIgnoreCase(normalized))
return CATEGORY;
if (PRODUCT.equalsIgnoreCase(normalized))
return PRODUCT;
return null;
}
@@ -486,18 +550,13 @@ public class PunchingService {
return Collections.unmodifiableMap(immutable);
}
private List<String> toVisibleSections(String sections) {
if (sections == null || sections.isBlank()) {
return List.of();
}
return List.of(sections.split(Pattern.quote(GlobalClass.ColDelim))).stream()
.map(String::trim)
.filter(section -> !section.isEmpty() && !"null".equalsIgnoreCase(section))
.distinct()
.toList();
}
private String defaultString(String value) {
return value == null ? "" : value;
}
private record DynamicContent(
String fields,
String html,
List<String> visibleSections) {
}
}

View File

@@ -18,6 +18,7 @@ import java.sql.Date;
import java.time.LocalDate;
import lib.exceptions.ApplicationException;
import lib.models.PunchedRecordsData;
import lib.models.CasePunching;
import lib.models.UserSession;
import lib.models.Option;
import matrix.services.commons.CommonService;
@@ -152,6 +153,40 @@ class PunchingServiceTest {
() -> options.put("other.", List.of()));
}
@Test
void preparesNewApplicationWithoutLegacyPunchingHandlerQueries() {
List<Call> databaseCalls = new ArrayList<>();
CygnusDbExecutor executor = (CygnusDbExecutor) Proxy.newProxyInstance(
getClass().getClassLoader(), new Class<?>[] {CygnusDbExecutor.class},
(proxy, method, args) -> {
if (!method.getName().equals("query") || args.length != 2) {
throw new UnsupportedOperationException(method.toString());
}
int queryId = (Integer) args[0];
databaseCalls.add(new Call(queryId, ((Object[]) args[1]).clone()));
return queryId == 10
? List.of(row(new LinkedHashMap<>(Map.of("control", "section1"))))
: List.of();
});
PunchingService service = new PunchingService(
new RecordingCommonService(), executor, new ObjectMapper());
CasePunching submitted = new CasePunching();
submitted.setPortfolioId((short) 38);
CasePunching result = service.prepareNewApplication(
submitted, (short) 5, (short) 1, (short) 9);
assertEquals(List.of(10, 74),
databaseCalls.stream().map(Call::queryId).toList());
assertArrayEquals(new Object[] {(short) 10, (short) 38},
databaseCalls.get(0).parameters());
assertArrayEquals(new Object[] {(short) 38, (short) 10, "ADDCASE"},
databaseCalls.get(1).parameters());
assertEquals(List.of("section1"), result.getVisibleSections());
assertEquals("", result.getDynamicHtml());
assertEquals("", result.getDynamicFields());
}
private static final class RecordingCommonService extends CommonService {
private final List<Call> calls = new ArrayList<>();