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