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