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.accounting.server.logic; 018 019import com.echothree.control.user.accounting.common.spec.GlAccountDescriptionSpec; 020import com.echothree.control.user.accounting.common.spec.GlAccountUniversalSpec; 021import com.echothree.model.control.accounting.common.exception.DuplicateGlAccountNameException; 022import com.echothree.model.control.accounting.common.exception.UnknownDefaultGlAccountException; 023import com.echothree.model.control.accounting.common.exception.UnknownGlAccountDescriptionException; 024import com.echothree.model.control.accounting.common.exception.UnknownGlAccountNameException; 025import com.echothree.model.control.accounting.server.control.AccountingControl; 026import com.echothree.model.control.core.common.ComponentVendors; 027import com.echothree.model.control.core.common.EntityTypes; 028import com.echothree.model.control.core.common.exception.InvalidParameterCountException; 029import com.echothree.model.control.core.server.logic.EntityInstanceLogic; 030import com.echothree.model.control.party.server.logic.LanguageLogic; 031import com.echothree.model.data.accounting.server.entity.Currency; 032import com.echothree.model.data.accounting.server.entity.GlAccount; 033import com.echothree.model.data.accounting.server.entity.GlAccountCategory; 034import com.echothree.model.data.accounting.server.entity.GlAccountClass; 035import com.echothree.model.data.accounting.server.entity.GlAccountDescription; 036import com.echothree.model.data.accounting.server.entity.GlAccountType; 037import com.echothree.model.data.accounting.server.entity.GlResourceType; 038import com.echothree.model.data.accounting.server.value.GlAccountDetailValue; 039import com.echothree.model.data.party.server.entity.Language; 040import com.echothree.util.common.message.ExecutionErrors; 041import com.echothree.util.common.persistence.BasePK; 042import com.echothree.util.server.control.BaseLogic; 043import com.echothree.util.server.message.ExecutionErrorAccumulator; 044import com.echothree.util.server.persistence.EntityPermission; 045import javax.enterprise.context.ApplicationScoped; 046import javax.inject.Inject; 047 048@ApplicationScoped 049public class GlAccountLogic 050 extends BaseLogic { 051 052 @Inject 053 AccountingControl accountingControl; 054 055 @Inject 056 EntityInstanceLogic entityInstanceLogic; 057 058 @Inject 059 GlAccountCategoryLogic glAccountCategoryLogic; 060 061 @Inject 062 LanguageLogic languageLogic; 063 064 protected GlAccountLogic() { 065 super(); 066 } 067 068 public GlAccount createGlAccount(final ExecutionErrorAccumulator eea, final String glAccountName, 069 final GlAccount parentGlAccount, final GlAccountType glAccountType, final GlAccountClass glAccountClass, 070 final GlAccountCategory glAccountCategory, final GlResourceType glResourceType, final Currency currency, 071 final Boolean isDefault, final Language language, final String description, final BasePK createdBy) { 072 var glAccount = accountingControl.getGlAccountByName(glAccountName); 073 074 if(glAccount == null) { 075 glAccount = accountingControl.createGlAccount(glAccountName, parentGlAccount, glAccountType, 076 glAccountClass, glAccountCategory, glResourceType, currency, isDefault, createdBy); 077 078 if(description != null) { 079 accountingControl.createGlAccountDescription(glAccount, language, description, createdBy); 080 } 081 } else { 082 handleExecutionError(DuplicateGlAccountNameException.class, eea, ExecutionErrors.DuplicateGlAccountName.name(), 083 glAccountName); 084 } 085 086 return glAccount; 087 } 088 089 public GlAccount getGlAccountByName(final ExecutionErrorAccumulator eea, final String glAccountName, 090 final EntityPermission entityPermission) { 091 var glAccount = accountingControl.getGlAccountByName(glAccountName, entityPermission); 092 093 if(glAccount == null) { 094 handleExecutionError(UnknownGlAccountNameException.class, eea, ExecutionErrors.UnknownGlAccountName.name(), glAccountName); 095 } 096 097 return glAccount; 098 } 099 100 public GlAccount getGlAccountByName(final ExecutionErrorAccumulator eea, final String glAccountName) { 101 return getGlAccountByName(eea, glAccountName, EntityPermission.READ_ONLY); 102 } 103 104 public GlAccount getGlAccountByNameForUpdate(final ExecutionErrorAccumulator eea, final String glAccountName) { 105 return getGlAccountByName(eea, glAccountName, EntityPermission.READ_WRITE); 106 } 107 108 public GlAccount getGlAccountByUniversalSpec(final ExecutionErrorAccumulator eea, final GlAccountUniversalSpec universalSpec, 109 final boolean allowDefault, final GlAccountCategory glAccountCategory, final EntityPermission entityPermission) { 110 GlAccount glAccount = null; 111 var glAccountName = universalSpec.getGlAccountName(); 112 var parameterCount = (glAccountName == null ? 0 : 1) + entityInstanceLogic.countPossibleEntitySpecs(universalSpec); 113 114 switch(parameterCount) { 115 case 0 -> { 116 if(allowDefault && glAccountCategory != null) { 117 glAccount = accountingControl.getDefaultGlAccount(glAccountCategory, entityPermission); 118 119 if(glAccount == null) { 120 handleExecutionError(UnknownDefaultGlAccountException.class, eea, ExecutionErrors.UnknownDefaultGlAccount.name()); 121 } 122 } else { 123 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 124 } 125 } 126 case 1 -> { 127 if(glAccountName == null) { 128 var entityInstance = entityInstanceLogic.getEntityInstance(eea, universalSpec, 129 ComponentVendors.ECHO_THREE.name(), EntityTypes.GlAccount.name()); 130 131 if(eea == null || !eea.hasExecutionErrors()) { 132 glAccount = accountingControl.getGlAccountByEntityInstance(entityInstance, entityPermission); 133 } 134 } else { 135 glAccount = getGlAccountByName(eea, glAccountName, entityPermission); 136 } 137 } 138 default -> 139 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 140 } 141 142 return glAccount; 143 } 144 145 public GlAccount getGlAccountByUniversalSpec(final ExecutionErrorAccumulator eea, final GlAccountUniversalSpec universalSpec, 146 final boolean allowDefault, final GlAccountCategory glAccountCategory) { 147 return getGlAccountByUniversalSpec(eea, universalSpec, allowDefault, glAccountCategory, EntityPermission.READ_ONLY); 148 } 149 150 public GlAccount getGlAccountByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, final GlAccountUniversalSpec universalSpec, 151 final boolean allowDefault, final GlAccountCategory glAccountCategory) { 152 return getGlAccountByUniversalSpec(eea, universalSpec, allowDefault, glAccountCategory, EntityPermission.READ_WRITE); 153 } 154 155 /** 156 * Obtain a GL Account fitting within a given GL Account Category. 157 * 158 * @param eea The ExecutionErrorAccumulator that any errors that are encountered should be added to. 159 * @param glAccounts A list of GlAccounts that will be drawn from to find a result. 160 * @param glAccountCategoryName If no glAccount is found in glAccounts, this will be used to find a default. 161 * @param unknownDefaultGlAccountError If no default is found, this error will be added to the ExecutionErrorAccumulator. 162 * @return The glAccount to use, unless null. 163 */ 164 public GlAccount getDefaultGlAccountByCategory(final ExecutionErrorAccumulator eea, final GlAccount[] glAccounts, 165 final String glAccountCategoryName, final String unknownDefaultGlAccountError) { 166 GlAccount glAccount = null; 167 168 for(var i = 0; glAccount == null && i < glAccounts.length ; i++) { 169 glAccount = glAccounts[i]; 170 } 171 172 if(glAccount == null) { 173 var glAccountCategory = glAccountCategoryLogic.getGlAccountCategoryByName(eea, glAccountCategoryName); 174 175 if(eea == null || !eea.hasExecutionErrors()) { 176 glAccount = accountingControl.getDefaultGlAccount(glAccountCategory); 177 178 if(glAccount == null) { 179 eea.addExecutionError(unknownDefaultGlAccountError); 180 } 181 } 182 } 183 184 return glAccount; 185 } 186 187 public GlAccountDescription getGlAccountDescriptionBySpec(final ExecutionErrorAccumulator eea, 188 final GlAccountDescriptionSpec spec, final EntityPermission entityPermission) { 189 GlAccountDescription glAccountDescription = null; 190 var glAccountName = spec.getGlAccountName(); 191 var glAccount = getGlAccountByName(eea, glAccountName); 192 193 if(!hasExecutionErrors(eea)) { 194 var languageIsoName = spec.getLanguageIsoName(); 195 var language = languageLogic.getLanguageByName(eea, languageIsoName); 196 197 if(!hasExecutionErrors(eea)) { 198 glAccountDescription = accountingControl.getGlAccountDescription(glAccount, language, entityPermission); 199 200 if(glAccountDescription == null) { 201 handleExecutionError(UnknownGlAccountDescriptionException.class, eea, ExecutionErrors.UnknownGlAccountDescription.name(), glAccountName, languageIsoName); 202 } 203 } 204 } 205 206 return glAccountDescription; 207 } 208 209 public void updateGlAccountFromValue(GlAccountDetailValue glAccountDetailValue, BasePK updatedBy) { 210 accountingControl.updateGlAccountFromValue(glAccountDetailValue, updatedBy); 211 } 212 213 public void deleteGlAccount(final ExecutionErrorAccumulator eea, final GlAccount glAccount, final BasePK deletedBy) { 214 accountingControl.deleteGlAccount(glAccount, deletedBy); 215 } 216 217}