001// -------------------------------------------------------------------------------- 002// Copyright 2002-2026 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.party.server.logic; 018 019import com.echothree.model.control.party.common.PartyRelationshipTypes; 020import com.echothree.model.control.party.common.PartyTypes; 021import com.echothree.model.control.party.common.RoleTypes; 022import com.echothree.model.control.party.common.exception.DuplicatePartyRelationshipException; 023import com.echothree.model.control.party.common.exception.NotAnEmployeeOfDepartmentsDivisionException; 024import com.echothree.model.control.party.common.exception.NotAnEmployeeOfDivisionsCompanyException; 025import com.echothree.model.control.party.common.exception.UnknownPartyRelationshipException; 026import com.echothree.model.control.party.common.exception.UnknownPartyRelationshipTypeNameException; 027import com.echothree.model.control.party.common.exception.UnknownRoleTypeNameException; 028import com.echothree.model.control.party.server.control.PartyControl; 029import com.echothree.model.control.user.server.logic.UserKeyLogic; 030import com.echothree.model.control.user.server.logic.UserSessionLogic; 031import com.echothree.model.data.party.server.entity.Party; 032import com.echothree.model.data.party.server.entity.PartyRelationship; 033import com.echothree.model.data.party.server.entity.PartyRelationshipType; 034import com.echothree.model.data.party.server.entity.RoleType; 035import com.echothree.util.common.message.ExecutionErrors; 036import com.echothree.util.common.persistence.BasePK; 037import com.echothree.util.server.control.BaseLogic; 038import com.echothree.util.server.message.ExecutionErrorAccumulator; 039import javax.enterprise.context.ApplicationScoped; 040import javax.enterprise.inject.spi.CDI; 041import javax.inject.Inject; 042 043@ApplicationScoped 044public class PartyRelationshipLogic 045 extends BaseLogic { 046 047 @Inject 048 PartyControl partyControl; 049 050 @Inject 051 PartyLogic partyLogic; 052 053 @Inject 054 UserKeyLogic userKeyLogic; 055 056 @Inject 057 UserSessionLogic userSessionLogic; 058 059 protected PartyRelationshipLogic() { 060 super(); 061 } 062 063 public static PartyRelationshipLogic getInstance() { 064 return CDI.current().select(PartyRelationshipLogic.class).get(); 065 } 066 067 public PartyRelationshipType getPartyRelationshipTypeByName(final ExecutionErrorAccumulator eea, final String partyRelationshipTypeName) { 068 var partyRelationshipType = partyControl.getPartyRelationshipTypeByName(partyRelationshipTypeName); 069 070 if(partyRelationshipType == null) { 071 handleExecutionError(UnknownPartyRelationshipTypeNameException.class, eea, ExecutionErrors.UnknownPartyRelationshipTypeName.name(), partyRelationshipTypeName); 072 } 073 074 return partyRelationshipType; 075 } 076 077 public RoleType getRoleTypeByName(final ExecutionErrorAccumulator eea, final String roleTypeName) { 078 var roleType = partyControl.getRoleTypeByName(roleTypeName); 079 080 if(roleType == null) { 081 handleExecutionError(UnknownRoleTypeNameException.class, eea, ExecutionErrors.UnknownRoleTypeName.name(), roleTypeName); 082 } 083 084 return roleType; 085 } 086 087 public PartyRelationship createPartyRelationship(final ExecutionErrorAccumulator eea, final PartyRelationshipType partyRelationshipType, 088 final Party fromParty, final RoleType fromRoleType, final Party toParty, final RoleType toRoleType, final BasePK createdBy) { 089 var partyRelationship = partyControl.getPartyRelationship(partyRelationshipType, fromParty, fromRoleType, toParty, toRoleType); 090 091 if(partyRelationship == null) { 092 partyControl.createPartyRelationship(partyRelationshipType, fromParty, fromRoleType, toParty, toRoleType, createdBy); 093 } else { 094 handleExecutionError(DuplicatePartyRelationshipException.class, eea, ExecutionErrors.DuplicatePartyRelationship.name(), 095 partyRelationshipType.getPartyRelationshipTypeName(), 096 fromParty.getLastDetail().getPartyName(), fromRoleType.getRoleTypeName(), 097 toParty.getLastDetail().getPartyName(), toRoleType.getRoleTypeName()); 098 } 099 100 return partyRelationship; 101 } 102 103 public void deletePartyRelationship(final ExecutionErrorAccumulator eea, final PartyRelationshipType partyRelationshipType, final Party fromParty, 104 final RoleType fromRoleType, final Party toParty, final RoleType toRoleType, final BasePK deletedBy) { 105 var partyRelationship = partyControl.getPartyRelationshipForUpdate(partyRelationshipType, fromParty, fromRoleType, toParty, toRoleType); 106 107 if(partyRelationship == null) { 108 handleExecutionError(UnknownPartyRelationshipException.class, eea, ExecutionErrors.UnknownPartyRelationship.name(), 109 partyRelationshipType.getPartyRelationshipTypeName(), 110 fromParty.getLastDetail().getPartyName(), fromRoleType.getRoleTypeName(), 111 toParty.getLastDetail().getPartyName(), toRoleType.getRoleTypeName()); 112 } else { 113 userKeyLogic.clearUserKeysByPartyRelationship(partyRelationship); 114 userSessionLogic.deleteUserSessionsByPartyRelationship(partyRelationship); 115 partyControl.deletePartyRelationship(partyRelationship, deletedBy); 116 } 117 } 118 119 public boolean isEmployeeOfCompany(final ExecutionErrorAccumulator eea, final Party company, final Party employee) { 120 var result = false; 121 122 partyLogic.checkPartyType(eea, company, PartyTypes.COMPANY.name()); 123 partyLogic.checkPartyType(eea, employee, PartyTypes.EMPLOYEE.name()); 124 125 if(!hasExecutionErrors(eea)) { 126 result = partyControl.countPartyRelationships(getPartyRelationshipTypeByName(eea, PartyRelationshipTypes.EMPLOYMENT.name()), 127 company, getRoleTypeByName(eea, RoleTypes.EMPLOYER.name()), 128 employee, getRoleTypeByName(eea, PartyTypes.EMPLOYEE.name())) == 1; 129 } 130 131 return result; 132 } 133 134 public PartyRelationship addEmployeeToCompany(final ExecutionErrorAccumulator eea, final Party companyParty, final Party employeeParty, final BasePK createdBy) { 135 PartyRelationship partyRelationship = null; 136 137 partyLogic.checkPartyType(eea, employeeParty, PartyTypes.EMPLOYEE.name()); 138 partyLogic.checkPartyType(eea, companyParty, PartyTypes.COMPANY.name()); 139 140 if(!hasExecutionErrors(eea)) { 141 partyRelationship = createPartyRelationship(eea, getPartyRelationshipTypeByName(eea, PartyRelationshipTypes.EMPLOYMENT.name()), 142 companyParty, getRoleTypeByName(eea, RoleTypes.EMPLOYER.name()), 143 employeeParty, getRoleTypeByName(eea, PartyTypes.EMPLOYEE.name()), createdBy); 144 } 145 146 return partyRelationship; 147 } 148 149 public void removeEmployeeFromCompany(final ExecutionErrorAccumulator eea, final Party companyParty, final Party employeeParty, final BasePK deletedBy) { 150 partyLogic.checkPartyType(eea, employeeParty, PartyTypes.EMPLOYEE.name()); 151 partyLogic.checkPartyType(eea, companyParty, PartyTypes.COMPANY.name()); 152 153 if(!hasExecutionErrors(eea)) { 154 removeEmployeeFromCompanysDivisions(eea, companyParty, employeeParty, deletedBy); 155 156 deletePartyRelationship(eea, getPartyRelationshipTypeByName(eea, PartyRelationshipTypes.EMPLOYMENT.name()), 157 companyParty, getRoleTypeByName(eea, RoleTypes.EMPLOYER.name()), 158 employeeParty, getRoleTypeByName(eea, PartyTypes.EMPLOYEE.name()), deletedBy); 159 } 160 } 161 162 public boolean isEmployeeOfDivision(final ExecutionErrorAccumulator eea, final Party division, final Party employee) { 163 var result = false; 164 165 partyLogic.checkPartyType(eea, division, PartyTypes.DIVISION.name()); 166 partyLogic.checkPartyType(eea, employee, PartyTypes.EMPLOYEE.name()); 167 168 if(!hasExecutionErrors(eea)) { 169 result = partyControl.countPartyRelationships(getPartyRelationshipTypeByName(eea, PartyRelationshipTypes.EMPLOYMENT.name()), 170 division, getRoleTypeByName(eea, RoleTypes.EMPLOYER.name()), 171 employee, getRoleTypeByName(eea, PartyTypes.EMPLOYEE.name())) == 1; 172 } 173 174 return result; 175 } 176 177 public PartyRelationship addEmployeeToDivision(final ExecutionErrorAccumulator eea, final Party divisionParty, final Party employeeParty, final BasePK createdBy) { 178 PartyRelationship partyRelationship = null; 179 180 partyLogic.checkPartyType(eea, employeeParty, PartyTypes.EMPLOYEE.name()); 181 partyLogic.checkPartyType(eea, divisionParty, PartyTypes.DIVISION.name()); 182 183 if(!hasExecutionErrors(eea)) { 184 var partyDivision = partyControl.getPartyDivision(divisionParty); 185 var partyCompany = partyControl.getPartyCompany(partyDivision.getCompanyParty()); 186 var companyParty = partyCompany.getParty(); 187 188 if(isEmployeeOfCompany(eea, companyParty, employeeParty)) { 189 partyRelationship = createPartyRelationship(eea, getPartyRelationshipTypeByName(eea, PartyRelationshipTypes.EMPLOYMENT.name()), 190 divisionParty, getRoleTypeByName(eea, RoleTypes.EMPLOYER.name()), 191 employeeParty, getRoleTypeByName(eea, PartyTypes.EMPLOYEE.name()), createdBy); 192 } else { 193 handleExecutionError(NotAnEmployeeOfDivisionsCompanyException.class, eea, ExecutionErrors.NotAnEmployeeOfDivisionsCompany.name(), 194 partyCompany.getPartyCompanyName(), employeeParty.getLastDetail().getPartyName()); 195 } 196 } 197 198 return partyRelationship; 199 } 200 201 public void removeEmployeeFromCompanysDivisions(final ExecutionErrorAccumulator eea, final Party companyParty, final Party employeeParty, final BasePK deletedBy) { 202 var partyDivisions = partyControl.getDivisionsByCompany(companyParty); 203 204 partyDivisions.stream().map((partyDivision) -> partyDivision.getParty()).filter((divisionParty) -> isEmployeeOfDivision(eea, divisionParty, employeeParty)).forEach((divisionParty) -> { 205 removeEmployeeFromDivisionsDepartments(eea, employeeParty, employeeParty, deletedBy); 206 removeEmployeeFromDivision(eea, divisionParty, employeeParty, deletedBy); 207 }); 208 } 209 210 public void removeEmployeeFromDivision(final ExecutionErrorAccumulator eea, final Party divisionParty, final Party employeeParty, final BasePK deletedBy) { 211 partyLogic.checkPartyType(eea, employeeParty, PartyTypes.EMPLOYEE.name()); 212 partyLogic.checkPartyType(eea, divisionParty, PartyTypes.DIVISION.name()); 213 214 if(!hasExecutionErrors(eea)) { 215 removeEmployeeFromDivisionsDepartments(eea, divisionParty, employeeParty, deletedBy); 216 217 deletePartyRelationship(eea, getPartyRelationshipTypeByName(eea, PartyRelationshipTypes.EMPLOYMENT.name()), 218 divisionParty, getRoleTypeByName(eea, RoleTypes.EMPLOYER.name()), 219 employeeParty, getRoleTypeByName(eea, PartyTypes.EMPLOYEE.name()), deletedBy); 220 } 221 } 222 223 public boolean isEmployeeOfDepartment(final ExecutionErrorAccumulator eea, final Party department, final Party employee) { 224 var result = false; 225 226 partyLogic.checkPartyType(eea, department, PartyTypes.DEPARTMENT.name()); 227 partyLogic.checkPartyType(eea, employee, PartyTypes.EMPLOYEE.name()); 228 229 if(!hasExecutionErrors(eea)) { 230 result = partyControl.countPartyRelationships(getPartyRelationshipTypeByName(eea, PartyRelationshipTypes.EMPLOYMENT.name()), 231 department, getRoleTypeByName(eea, RoleTypes.EMPLOYER.name()), 232 employee, getRoleTypeByName(eea, PartyTypes.EMPLOYEE.name())) == 1; 233 } 234 235 return result; 236 } 237 238 public PartyRelationship addEmployeeToDepartment(final ExecutionErrorAccumulator eea, final Party departmentParty, final Party employeeParty, final BasePK createdBy) { 239 PartyRelationship partyRelationship = null; 240 241 partyLogic.checkPartyType(eea, employeeParty, PartyTypes.EMPLOYEE.name()); 242 partyLogic.checkPartyType(eea, departmentParty, PartyTypes.DEPARTMENT.name()); 243 244 if(!hasExecutionErrors(eea)) { 245 var partyDepartment = partyControl.getPartyDepartment(departmentParty); 246 var partyDivision = partyControl.getPartyDivision(partyDepartment.getDivisionParty()); 247 var partyCompany = partyControl.getPartyCompany(partyDivision.getCompanyParty()); 248 var divisionParty = partyDivision.getParty(); 249 250 if(isEmployeeOfDivision(eea, divisionParty, employeeParty)) { 251 partyRelationship = createPartyRelationship(eea, getPartyRelationshipTypeByName(eea, PartyRelationshipTypes.EMPLOYMENT.name()), 252 departmentParty, getRoleTypeByName(eea, RoleTypes.EMPLOYER.name()), 253 employeeParty, getRoleTypeByName(eea, PartyTypes.EMPLOYEE.name()), createdBy); 254 } else { 255 handleExecutionError(NotAnEmployeeOfDepartmentsDivisionException.class, eea, ExecutionErrors.NotAnEmployeeOfDepartmentsDivision.name(), 256 partyCompany.getPartyCompanyName(), partyDivision.getPartyDivisionName(), employeeParty.getLastDetail().getPartyName()); 257 } 258 } 259 260 return partyRelationship; 261 } 262 263 public void removeEmployeeFromDivisionsDepartments(final ExecutionErrorAccumulator eea, final Party divisionParty, final Party employeeParty, final BasePK deletedBy) { 264 var partyDepartments = partyControl.getDepartmentsByDivision(divisionParty); 265 266 partyDepartments.stream().map((partyDepartment) -> partyDepartment.getParty()).filter((departmentParty) -> isEmployeeOfDepartment(eea, departmentParty, employeeParty)).forEach((departmentParty) -> { 267 removeEmployeeFromDepartment(eea, departmentParty, employeeParty, deletedBy); 268 }); 269 } 270 271 public void removeEmployeeFromDepartment(final ExecutionErrorAccumulator eea, final Party departmentParty, final Party employeeParty, final BasePK deletedBy) { 272 partyLogic.checkPartyType(eea, employeeParty, PartyTypes.EMPLOYEE.name()); 273 partyLogic.checkPartyType(eea, departmentParty, PartyTypes.DEPARTMENT.name()); 274 275 if(!hasExecutionErrors(eea)) { 276 deletePartyRelationship(eea, getPartyRelationshipTypeByName(eea, PartyRelationshipTypes.EMPLOYMENT.name()), 277 departmentParty, getRoleTypeByName(eea, RoleTypes.EMPLOYER.name()), 278 employeeParty, getRoleTypeByName(eea, PartyTypes.EMPLOYEE.name()), deletedBy); 279 } 280 } 281 282}