diff --git a/backend/src/main/java/com/nttdata/calender/LoggerTemplates.java b/backend/src/main/java/com/nttdata/calender/LoggerTemplates.java new file mode 100644 index 0000000..7f89f72 --- /dev/null +++ b/backend/src/main/java/com/nttdata/calender/LoggerTemplates.java @@ -0,0 +1,29 @@ +package com.nttdata.calender; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import com.bmc.arsys.api.ARException; +import com.nttdata.calender.api.RemedyJavaAPI; + +public class LoggerTemplates { + private RemedyJavaAPI api; + private static final Logger applicationLogger = LogManager.getLogger("application"); + + public LoggerTemplates(RemedyJavaAPI api) { + this.api = api; + } + + public void initLog(String requestName, String userName) throws ARException { + applicationLogger.info("\n\n\nRequest: " + requestName + "\nUser: " + api.getUser() + "\nAdmin? " + + (this.api.isAdministrator() ? "Yes" : "No")); + } + + public void qualifierLog(String form, String qualifier) { + applicationLogger.info("\nForm: " + form + "\nQualifier: " + qualifier); + } + + public void sizeLog() { + + } +} diff --git a/backend/src/main/java/com/nttdata/calender/api/RemedyJavaAPI.java b/backend/src/main/java/com/nttdata/calender/api/RemedyJavaAPI.java index ba2fefd..f3deef0 100644 --- a/backend/src/main/java/com/nttdata/calender/api/RemedyJavaAPI.java +++ b/backend/src/main/java/com/nttdata/calender/api/RemedyJavaAPI.java @@ -47,7 +47,6 @@ public class RemedyJavaAPI { server.setPort(46262); this.connect(); - // TODO: move to APIApplication.java or State.java - see where it fits State.getInstance().queryState(this); SupportGroup.getInstance().querySupportGroups(this); @@ -140,21 +139,20 @@ public class RemedyJavaAPI { public String deleteEntry(String formName, String entryId) throws ARException { // Specify 0 for the deleteOption as mentioned in the documentation int deleteOption = 0; - + // Attempt to delete the entry server.deleteEntry(formName, entryId, deleteOption); - + // Check for any status or warnings after the deletion var lastStatus = server.getLastStatus(); if (!lastStatus.isEmpty()) { applicationLogger.warn("Warning after deleting entry: " + lastStatus); return "Warning: " + lastStatus.toString(); } - + applicationLogger.info("Entry with ID " + entryId + " deleted successfully from form " + formName); return "Entry deleted successfully. ID: " + entryId; } - /** * Takes an entry ID and a {@link Query} object with values and updates the @@ -351,6 +349,7 @@ public class RemedyJavaAPI { } } + public boolean isAdministrator() throws ARException { return server.isAdministrator(); } diff --git a/backend/src/main/java/com/nttdata/calender/changes/Change.java b/backend/src/main/java/com/nttdata/calender/changes/Change.java index 9478203..caf0ec2 100644 --- a/backend/src/main/java/com/nttdata/calender/changes/Change.java +++ b/backend/src/main/java/com/nttdata/calender/changes/Change.java @@ -7,6 +7,8 @@ import java.util.Date; import java.util.Optional; import java.util.TimeZone; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.bmc.arsys.api.ARException; @@ -15,6 +17,7 @@ import com.bmc.arsys.api.SortInfo; import com.bmc.arsys.api.Timestamp; import com.bmc.arsys.api.Value; import com.nttdata.calender.DateConverter; +import com.nttdata.calender.LoggerTemplates; import com.nttdata.calender.api.Query; import com.nttdata.calender.api.RemedyJavaAPI; import com.nttdata.calender.changes.query.FilterElement; @@ -63,6 +66,8 @@ public class Change { .addFieldId("Contract", 670031002) .addFieldId("PlanTimeHours", 666000009) .addFieldId("PlanTimeMinutes", 666000010) + .addFieldId("Approval", 1000003278) + .addFieldId("ApprovalProcessName", 301322300) .build(); } @@ -79,7 +84,8 @@ public class Change { * @throws ValidationError if there is an invalid filter or qualification */ public ChangeResponse get(ChangeRequest request) throws ARException, NotFoundError, ValidationError { - // api.impersonateUser("ext_StanzPa"); + + LoggerTemplates log = new LoggerTemplates(api); var peopleFullName = processPeopleInfo(request); @@ -87,17 +93,47 @@ public class Change { var qualifier = filter.constructQualifier(queryChange, api); SortInfo sort = request.constructSortInfo(queryChange); + log.initLog("getChanges", api.getUser()); // Logging + var entries = api.queryFieldsById(qualifier, this.queryChange.getFieldIds(), this.queryChange.getFormName(), sort, request.getSliceStart(), request.getSliceEnd()); - System.out.println(qualifier); // "\'1000000182\'!=\".\"" + log.qualifierLog(queryChange.getFormName(), qualifier); // Logging + + System.out.println(qualifier); + var entriesSize = api.getFormSize(qualifier, this.queryChange.getFormName()); var changes = new ArrayList(); for (var entry : entries) { var change = new ChangeItem(entry.getEntryId()); + + boolean approval = getValueStringByID(entry, "Approval").equals("0") ? true : false; + + if (approval) { + var queryApproval = new Query.QueryBuilder("CHG:ChangeAPDetailSignature") + .addFieldId("Approvers", 13207).build(); + + String qual = "(\'1000000182\' = \"" + getValueStringByID(entry, "ChangeNr") + + "\") AND (\'10000\' = \"" + + getValueStringByID(entry, "ApprovalProcessName") + + "\") AND (\'13207\' LIKE \"%" + api.getUser() + "%\")"; + + var queryApprovalProcessName = api.queryFieldsById(qual, + queryApproval.getFieldIds(), queryApproval.getFormName(), sort, 0, 0); + + log.qualifierLog(queryApproval.getFormName(), qual); + + if (!queryApprovalProcessName.isEmpty() && queryApprovalProcessName != null + && queryApprovalProcessName.size() > 0) + change.setApproval(true); + else + change.setApproval(false); + + } + change.setChangeNr(getValueStringByID(entry, "ChangeNr")); change.setSupportGroup(getValueStringByID(entry, "SupportGroup")); change.setState(Optional.ofNullable(getValue(entry, "State")) @@ -124,24 +160,6 @@ public class Change { .map(Object::toString) .filter(peopleFullName::equals) .isPresent()); - - /* - * var state = getValue(entry, "State").getIntValue(); - * var inApproval = inApprovalList(api.getUser(), getValueStringByID(entry, - * "ChangeNr")); - * - * change.setFlagPermit(flagPermit(state)); - * change.setFlagApprove(flagApproval(inApproval, state)); - * change.setFlagReject(flagApproval(inApproval, state)); - * change.setFlagCancel(flagCancel(getValueStringByID(entry, "SupportGroupId"), - * state)); - */ - - // change.setFlagPermit(flagPermit(state)); - // change.setFlagApprove(flagApproval(inApproval, state)); - // change.setFlagReject(flagApproval(inApproval, state)); - // change.setFlagCancel(flagCancel(getValueStringByID(entry, "SupportGroupId"), - // state)); change.setPackageName(queryPackageName(getValueStringByID(entry, "PackageType").toString())); var ptMinutes = getValueStringByID(entry, "PlanTimeMinutes").isEmpty() ? "00" @@ -192,7 +210,7 @@ public class Change { throw new NotFoundError("No supportGroups associated to the loginId "); } // request.addFilter( - // new FilterElement("SupportGroupId", "equals", peopleSupportGroup)); + // new FilterElement("SupportGroupId", "equals", peopleSupportGroup)); return peopleInfos.get(0).get(queryPerson.getFieldId("FullName")).toString(); } diff --git a/backend/src/main/java/com/nttdata/calender/changes/ChangeItem.java b/backend/src/main/java/com/nttdata/calender/changes/ChangeItem.java index c562e44..238cb01 100644 --- a/backend/src/main/java/com/nttdata/calender/changes/ChangeItem.java +++ b/backend/src/main/java/com/nttdata/calender/changes/ChangeItem.java @@ -33,6 +33,7 @@ public class ChangeItem { private Date D3; private Date D4; private double planTime; + private boolean approval; // private boolean flagPermit; // private boolean flagApprove; // private boolean flagReject; @@ -140,7 +141,7 @@ public class ChangeItem { public ChangeItem(String resourceId, String resourceName, String changeNr, int state, String contract, String supportGroup, String coordinatorSgId, String coordinatorSg, String supportGroupId, String providerCluster, String approvalStatus, String statusReason, Date D1, Date D2, Date D3, Date D4, - String changeImplementer, String changeImplementerLogin, String changeImplementerPersonId) { + String changeImplementer, String changeImplementerLogin, String changeImplementerPersonId, boolean approval) { this.resourceId = resourceId; this.resourceName = resourceName; this.changeNr = changeNr; @@ -160,88 +161,16 @@ public class ChangeItem { this.changeImplementer = changeImplementer; this.changeImplementerLogin = changeImplementerLogin; this.changeImplementerPersonId = changeImplementerPersonId; + this.approval = approval; } - // /** - // * Retrieves the flag indicating whether the change item has a permit. - // * - // * @return {@code true} if the change item has a permit, {@code false} - // * otherwise. - // */ - // public boolean getFlagPermit() { - // return this.flagPermit; - // } + public boolean isApproval() { + return approval; + } - // /** - // * Sets the flag indicating whether the change item has a permit. - // * - // * @param flagPermit {@code true} if the change item has a permit, {@code - // false} - // * otherwise. - // */ - // public void setFlagPermit(boolean flagPermit) { - // this.flagPermit = flagPermit; - // } - - // /** - // * Retrieves the flag indicating whether the change item has been approved. - // * - // * @return {@code true} if the change item has been approved, {@code false} - // * otherwise. - // */ - // public boolean getFlagApprove() { - // return this.flagApprove; - // } - - // /** - // * Sets the flag indicating whether the change item has been approved. - // * - // * @param flagApprove {@code true} if the change item has been approved, - // * {@code false} otherwise. - // */ - // public void setFlagApprove(boolean flagApprove) { - // this.flagApprove = flagApprove; - // } - - // /** - // * Retrieves the flag indicating whether the change item has been rejected. - // * - // * @return {@code true} if the change item has been rejected, {@code false} - // * otherwise. - // */ - // public boolean getFlagReject() { - // return this.flagReject; - // } - - // /** - // * Sets the flag indicating whether the change item has been rejected. - // * - // * @param flagReject {@code true} if the change item has been rejected, - // * {@code false} otherwise. - // */ - // public void setFlagReject(boolean flagReject) { - // this.flagReject = flagReject; - // } - - // /** - // * Retrieves the flag indicating whether the change item has been canceled. - // * - // * @return {@code true} if the change item has been canceled, {@code false} - // * otherwise. - // */ - // public boolean getFlagCancel() { - // return this.flagCancel; - // } - - // /** - // * Sets the flag indicating whether the change item has been canceled. - // * - // * @param flagCancel {@code true} if the change item has been canceled, - // * {@code false} otherwise. - // */ - // public void setFlagCancel(boolean flagCancel) { - // this.flagCancel = flagCancel; - // } + public void setApproval(boolean approval) { + this.approval = approval; + } /** * Retrieves the planned time. diff --git a/backend/src/main/java/com/nttdata/calender/planTimes/PlanTimes.java b/backend/src/main/java/com/nttdata/calender/planTimes/PlanTimes.java index 92f0cb5..af38396 100644 --- a/backend/src/main/java/com/nttdata/calender/planTimes/PlanTimes.java +++ b/backend/src/main/java/com/nttdata/calender/planTimes/PlanTimes.java @@ -87,7 +87,6 @@ public class PlanTimes { var minutes = change.get(queryChanges.getFieldId("PlanTimeMinutes")).toString(); var hours = change.get(queryChanges.getFieldId("PlanTimeHours")).toString(); double plantime = convertPlanTime(hours, minutes); - System.out.println(plantime); planTimePerWeek += plantime; } } diff --git a/backend/src/main/java/com/nttdata/calender/states/State.java b/backend/src/main/java/com/nttdata/calender/states/State.java index dc6172e..5540a91 100644 --- a/backend/src/main/java/com/nttdata/calender/states/State.java +++ b/backend/src/main/java/com/nttdata/calender/states/State.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import com.bmc.arsys.api.ARException; import com.bmc.arsys.api.Entry; @@ -68,7 +69,7 @@ public class State { * @throws ARException */ public void queryState(RemedyJavaAPI api) throws ARException, NotFoundError { - queryStateNames(api); + // queryStateNames(api); queryPossibleStates(api); if (state.isEmpty()) { @@ -88,16 +89,91 @@ public class State { */ public void queryPossibleStates(RemedyJavaAPI api) throws ARException { var configurationQuery = new Query.QueryBuilder("ITSM:Configuration") - .addFieldId("stateTransitionField", 700003001) - .addFieldId("englishName", 700003002) - .addFieldId("possibleState", 700003006) + .addFieldId("engName", 700003002) + .addFieldId("gerName", 700003003) + .addFieldId("cancelFlag", 700003004) .addFieldId("actualState", 700003005) + .addFieldId("restartFlag", 700003010) + .addFieldId("implementerFlag", 700003012) + .addFieldId("possibleState", 700003006) // Include possibleState here .build(); - var stateFields = api.queryFieldsById("\'Menu\' = \"CHANGE_CALENDER_STATUS_TRANSITIONS\"", + var configurationStatusQuery = new Query.QueryBuilder("ITSM:Configuration") + .addFieldId("actualState", 700003005) + .addFieldId("possibleState", 700003006) + .build(); + + var stateFields = api.queryFieldsById("\'Menu\' = \"CHANGE_CALENDER_STATUS\"", configurationQuery.getFieldIds(), configurationQuery.getFormName(), null, 0, 0); - updatePossibleStates(stateFields, configurationQuery); + + var stateStatusFields = api.queryFieldsById("\'Menu\' = \"CHANGE_CALENDER_STATUS_TRANSITIONS\"", + configurationStatusQuery.getFieldIds(), + configurationStatusQuery.getFormName(), null, 0, 0); + + populateStateInfo(stateFields, stateStatusFields, configurationQuery, configurationStatusQuery); + + // Print state information + printStateInfo(); + } + + private void populateStateInfo(List stateFields, List stateStatusFields, + Query configurationQuery, Query configurationStatusQuery) throws ARException { + for (var stateField : stateFields) { + int actualState = stateField.get(configurationQuery.getFieldId("actualState")).getIntValue(); + + boolean cancelFlag = false; + boolean restartFlag = false; + boolean implementerFlag = false; + + try { + // Extract additional fields + cancelFlag = stateField.get(configurationQuery.getFieldId("cancelFlag")).toString() + .equals("CANCEL_YES"); + restartFlag = stateField.get(configurationQuery.getFieldId("restartFlag")).toString() + .equals("RESTARTALLOWED_YES"); + implementerFlag = stateField.get(configurationQuery.getFieldId("implementerFlag")).toString() + .equals("SETIMPLEMENTER_YES"); + } catch (Exception e) { + e.printStackTrace(); + } + + String engName = stateField.get(configurationQuery.getFieldId("engName")).toString(); + String gerName = stateField.get(configurationQuery.getFieldId("gerName")).toString(); + + // Initialize StateInfo with additional fields + StateInfo stateInfo = new StateInfo(engName, gerName, cancelFlag, restartFlag, implementerFlag); + + for (var statusField : stateStatusFields) { + int statusActualState = statusField.get(configurationStatusQuery.getFieldId("actualState")) + .getIntValue(); + + if (actualState == statusActualState) { + int possibleState = statusField.get(configurationStatusQuery.getFieldId("possibleState")) + .getIntValue(); + stateInfo.addPossibleState(possibleState); + } + } + + // Add StateInfo to the state HashMap + getState().put(actualState, stateInfo); + } + } + + private void printStateInfo() { + for (var state : get()) { + // Join possible states into a single string + String possibleStatesString = String.join(", ", + state.possibleStates.stream().map(Object::toString).collect(Collectors.toList())); + + // Print the state information + System.out.printf("\n\n[%s]\n[%s]\n[%s]\n[%s]\n[%b]\n[%b]\n[%b]\n\n", + state.actualState, state.stateNameDE, state.stateNameEN, + possibleStatesString, state.cancelFlag, state.restartFlag, state.implementerFlag); + + // Print the number of possible states + System.out.println("Possible States: " + state.possibleStates.size()); + } } /** @@ -107,14 +183,16 @@ public class State { * @param stateFields List of Entry to be processed * @param configurationQuery Query object of stateFields */ - public void updatePossibleStates(List stateFields, Query configurationQuery) { - stateFields.stream().forEach(entry -> { - var actualState = entry.get(configurationQuery.getFieldId("actualState")).getIntValue(); - var possibleState = entry.get(configurationQuery.getFieldId("possibleState")).getIntValue(); - this.getState().get(actualState).addPossibleState(possibleState); - }); - } - + // public void updatePossibleStates(List stateFields, Query + // configurationQuery) { + // stateFields.stream().forEach(entry -> { + // var actualState = + // entry.get(configurationQuery.getFieldId("actualState")).getIntValue(); + // var possibleState = + // entry.get(configurationQuery.getFieldId("possibleState")).getIntValue(); + // this.getState().get(actualState).addPossibleState(possibleState); + // }); + // } /** * Query the German state name from the specified form. The German name in the * form is associated with the English one. For merging the names into the @@ -124,22 +202,19 @@ public class State { * @param api Remedy API object * @throws ARException if an error occurs during the query */ - private void queryStateNames(RemedyJavaAPI api) throws ARException { - var nameQuery = new Query.QueryBuilder("SYS:Menu Items Locale LkUp") - .addFieldId("englishName", 1000004339) - .addFieldId("germanName", 1000004338) - .addFieldId("Locale", 1000004342) - .addFieldId("SelectionCode", 1000004336) - .build(); - - var stateNames = api.queryFieldsById("\'Menu Type\' = \"Change Status Values\"", - nameQuery.getFieldIds(), - nameQuery.getFormName(), null, 0, 0); - - updateStateNames(stateNames, nameQuery); - - } - + // private void queryStateNames(RemedyJavaAPI api) throws ARException { + // var nameQuery = new Query.QueryBuilder("SYS:Menu Items Locale LkUp") + // .addFieldId("englishName", 1000004339) + // .addFieldId("germanName", 1000004338) + // .addFieldId("Locale", 1000004342) + // .addFieldId("SelectionCode", 1000004336) + // .build(); + // var stateNames = api.queryFieldsById("\'Menu Type\' = \"Change Status + // Values\"", + // nameQuery.getFieldIds(), + // nameQuery.getFormName(), null, 0, 0); + // updateStateNames(stateNames, nameQuery); + // } /** * Takes the relevant data about state names out of the {@code List} and * processes them to be saved into the State. @@ -147,24 +222,24 @@ public class State { * @param stateFields List of Entry to be processed * @param nameQuery Query object of stateFields */ - public void updateStateNames(List stateFields, Query nameQuery) { - stateFields.stream() - .filter(entry -> Optional.ofNullable(entry.get(nameQuery.getFieldId("Locale"))) - .map(Object::toString) - .orElse("") - .equals("de")) - .forEach( - entry -> { - var selectionCode = nameQuery.getFieldId("SelectionCode"); - var englishName = nameQuery.getFieldId("englishName"); - var germanName = nameQuery.getFieldId("germanName"); - - this.getState().put(entry.get(selectionCode).getIntValue(), - new StateInfo(entry.get(englishName).toString(), - entry.get(germanName).toString())); - }); - } + // public void updateStateNames(List stateFields, Query nameQuery) { + // stateFields.stream() + // .filter(entry -> + // Optional.ofNullable(entry.get(nameQuery.getFieldId("Locale"))) + // .map(Object::toString) + // .orElse("") + // .equals("de")) + // .forEach( + // entry -> { + // var selectionCode = nameQuery.getFieldId("SelectionCode"); + // var englishName = nameQuery.getFieldId("englishName"); + // var germanName = nameQuery.getFieldId("germanName"); + // this.getState().put(entry.get(selectionCode).getIntValue(), + // new StateInfo(entry.get(englishName).toString(), + // entry.get(germanName).toString())); + // }); + // } /** * Generate an Array of JSON objects that consists of all the state information. * These are the integer representation of the actual state, an Array of integer @@ -174,10 +249,12 @@ public class State { * @return Array of JSON objects with integer representation of state and * {@link StateInfo} */ + public ArrayList get() { var response = new ArrayList(); this.state.forEach((key, value) -> { - response.add(new StateResponse(key, value.possibleState, value.stateNameEN, value.stateNameDE)); + response.add(new StateResponse(key, value.possibleState, value.stateNameEN, value.stateNameDE, + value.cancelFlag, value.restartFlag, value.implementerFlag)); }); return response; } @@ -189,6 +266,9 @@ public class State { String stateNameEN; String stateNameDE; ArrayList possibleState; + boolean cancelFlag; + boolean restartFlag; + boolean implementerFlag; /** * Initializes an instance of the {@link StateInfo} class. @@ -210,10 +290,14 @@ public class State { * @param stateNameEN state name in English * @param stateNameDE state name in German */ - public StateInfo(String stateNameEN, String stateNameDE) { - this.possibleState = new ArrayList<>(); + public StateInfo(String stateNameEN, String stateNameDE, boolean cancelFlag, boolean restartFlag, + boolean implementerFlag) { this.stateNameEN = stateNameEN; this.stateNameDE = stateNameDE; + this.cancelFlag = cancelFlag; + this.restartFlag = restartFlag; + this.implementerFlag = implementerFlag; + this.possibleState = new ArrayList<>(); } /** @@ -263,6 +347,5 @@ public class State { public void setStateNameEN(String stateNameEN) { this.stateNameEN = stateNameEN; } - } } diff --git a/backend/src/main/java/com/nttdata/calender/states/StateResponse.java b/backend/src/main/java/com/nttdata/calender/states/StateResponse.java index 4252145..93c3902 100644 --- a/backend/src/main/java/com/nttdata/calender/states/StateResponse.java +++ b/backend/src/main/java/com/nttdata/calender/states/StateResponse.java @@ -10,6 +10,9 @@ public class StateResponse { public ArrayList possibleStates; public String stateNameEN; public String stateNameDE; + public boolean cancelFlag; + public boolean restartFlag; + public boolean implementerFlag; /** * Initialize the instance of the JSON response. @@ -20,11 +23,19 @@ public class StateResponse { * @param stateNameDE state name in german */ public StateResponse(int actualState, ArrayList possibleState, String stateNameEN, - String stateNameDE) { + String stateNameDE, boolean cancelFlag, boolean restartFlag, boolean implemeneterFlag) { this.actualState = actualState; this.possibleStates = possibleState; this.stateNameEN = stateNameEN; this.stateNameDE = stateNameDE; + this.cancelFlag = cancelFlag; + this.restartFlag = restartFlag; + this.implementerFlag = implemeneterFlag; + } + + public Object get(int englishName) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'get'"); } }