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