001// -------------------------------------------------------------------------------- 002// Copyright 2002-2024 Echo Three, LLC 003// 004// Licensed under the Apache License, Version 2.0 (the "License"); 005// you may not use this file except in compliance with the License. 006// You may obtain a copy of the License at 007// 008// http://www.apache.org/licenses/LICENSE-2.0 009// 010// Unless required by applicable law or agreed to in writing, software 011// distributed under the License is distributed on an "AS IS" BASIS, 012// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013// See the License for the specific language governing permissions and 014// limitations under the License. 015// -------------------------------------------------------------------------------- 016 017package com.echothree.model.control.training.server.trigger; 018 019import com.echothree.model.control.core.common.EventTypes; 020import com.echothree.model.control.core.server.control.CoreControl; 021import com.echothree.model.control.security.server.control.SecurityControl; 022import com.echothree.model.control.training.server.control.TrainingControl; 023import com.echothree.model.control.training.server.logic.PartyTrainingClassLogic; 024import com.echothree.model.control.training.server.logic.PartyTrainingClassLogic.PreparedPartyTrainingClass; 025import com.echothree.model.control.training.common.training.PartyTrainingClassStatusConstants; 026import com.echothree.model.control.workflow.server.control.WorkflowControl; 027import com.echothree.model.control.workflow.server.trigger.BaseTrigger; 028import com.echothree.model.control.workflow.server.trigger.EntityTypeTrigger; 029import com.echothree.model.data.party.common.pk.PartyPK; 030import com.echothree.model.data.party.server.entity.Party; 031import com.echothree.model.data.security.server.entity.PartySecurityRoleTemplateUse; 032import com.echothree.model.data.training.server.entity.PartyTrainingClass; 033import com.echothree.model.data.training.server.entity.PartyTrainingClassDetail; 034import com.echothree.model.data.training.server.entity.TrainingClass; 035import com.echothree.model.data.workflow.server.entity.WorkflowEntityStatus; 036import com.echothree.util.server.message.ExecutionErrorAccumulator; 037import com.echothree.util.server.persistence.Session; 038import java.util.Set; 039 040public class PartyTrainingClassTrigger 041 extends BaseTrigger 042 implements EntityTypeTrigger { 043 044 private void expireCurrentPartyTrainingClass(final Session session, final ExecutionErrorAccumulator eea, final WorkflowEntityStatus workflowEntityStatus, 045 final PartyTrainingClass partyTrainingClass, final PartyPK triggeredBy) { 046 var coreControl = Session.getModelController(CoreControl.class); 047 var trainingControl = Session.getModelController(TrainingControl.class); 048 var workflowControl = Session.getModelController(WorkflowControl.class); 049 PartyTrainingClassDetail partyTrainingClassDetail = partyTrainingClass.getLastDetail(); 050 Party party = partyTrainingClassDetail.getParty(); 051 TrainingClass trainingClass = partyTrainingClassDetail.getTrainingClass(); 052 053 workflowControl.transitionEntityInWorkflowUsingNames(null, workflowEntityStatus, PartyTrainingClassStatusConstants.WorkflowDestination_PASSED_TO_EXPIRED, 054 trainingClass.getLastDetail().getExpiredRetentionTime(), triggeredBy); 055 coreControl.sendEvent(partyTrainingClassDetail.getParty().getPrimaryKey(), EventTypes.TOUCH, partyTrainingClass.getPrimaryKey(), EventTypes.MODIFY, triggeredBy); 056 057 // If it is required, then consider creating a new PartyTrainingClass that's assigned to them. 058 if(checkTrainingRequired(party, trainingClass)) { 059 // Check to see if the TrainingClass is in one of the listed statuses for the Party. If it is, then we do not create a 060 // new instance of a PartyTrainingClass for it. 061 Set<PartyTrainingClass> partyTrainingClasses = trainingControl.getPartyTrainingClassesByStatuses(party, trainingClass, 062 PartyTrainingClassStatusConstants.WorkflowStep_ASSIGNED, PartyTrainingClassStatusConstants.WorkflowStep_TRAINING, 063 PartyTrainingClassStatusConstants.WorkflowStep_PASSED); 064 065 if(partyTrainingClasses.isEmpty()) { 066 PartyTrainingClassLogic partyTrainingClassLogic = PartyTrainingClassLogic.getInstance(); 067 PreparedPartyTrainingClass preparedPartyTrainingClass = partyTrainingClassLogic.preparePartyTrainingClass(eea, party, trainingClass, null, null); 068 069 if(!eea.hasExecutionErrors()) { 070 partyTrainingClassLogic.createPartyTrainingClass(session, preparedPartyTrainingClass, triggeredBy); 071 } 072 } 073 } 074 } 075 076 private boolean checkTrainingRequired(final Party party, final TrainingClass trainingClass) { 077 boolean trainingRequired = false; 078 079 // Check AlwaysReassignOnExpiration on the TrainingClass, and if that isn't set, check to see if the Party has a 080 // PartySecurityRoleTemplateUse. If the PartySecurityRoleTemplate lists this TrainingClass, then it will be required. 081 if(trainingClass.getLastDetail().getAlwaysReassignOnExpiration()) { 082 trainingRequired = true; 083 } else { 084 var securityControl = Session.getModelController(SecurityControl.class); 085 PartySecurityRoleTemplateUse partySecurityRoleTemplateUse = securityControl.getPartySecurityRoleTemplateUse(party); 086 if(partySecurityRoleTemplateUse != null) { 087 if(securityControl.getPartySecurityRoleTemplateTrainingClass(partySecurityRoleTemplateUse.getPartySecurityRoleTemplate(), trainingClass) != null) { 088 trainingRequired = true; 089 } 090 } 091 } 092 093 return trainingRequired; 094 } 095 096 @Override 097 public void handleTrigger(final Session session, final ExecutionErrorAccumulator eea, final WorkflowEntityStatus workflowEntityStatus, final PartyPK triggeredBy) { 098 var trainingControl = Session.getModelController(TrainingControl.class); 099 PartyTrainingClass partyTrainingClass = trainingControl.convertEntityInstanceToPartyTrainingClassForUpdate(getEntityInstance(workflowEntityStatus)); 100 String workflowStepName = getWorkflowStepName(workflowEntityStatus); 101 102 if(workflowStepName.equals(PartyTrainingClassStatusConstants.WorkflowStep_PASSED)) { 103 expireCurrentPartyTrainingClass(session, eea, workflowEntityStatus, partyTrainingClass, triggeredBy); 104 } else if(workflowStepName.equals(PartyTrainingClassStatusConstants.WorkflowStep_EXPIRED)) { 105 trainingControl.deletePartyTrainingClass(partyTrainingClass, triggeredBy); 106 } 107 } 108 109}