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.ItemAccountingCategoryDescriptionSpec; 020import com.echothree.control.user.accounting.common.spec.ItemAccountingCategoryUniversalSpec; 021import com.echothree.model.control.accounting.common.exception.DuplicateItemAccountingCategoryNameException; 022import com.echothree.model.control.accounting.common.exception.UnknownDefaultItemAccountingCategoryException; 023import com.echothree.model.control.accounting.common.exception.UnknownItemAccountingCategoryDescriptionException; 024import com.echothree.model.control.accounting.common.exception.UnknownItemAccountingCategoryNameException; 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.item.server.control.ItemControl; 031import com.echothree.model.control.party.server.logic.LanguageLogic; 032import com.echothree.model.data.accounting.server.entity.GlAccount; 033import com.echothree.model.data.accounting.server.entity.ItemAccountingCategory; 034import com.echothree.model.data.accounting.server.entity.ItemAccountingCategoryDescription; 035import com.echothree.model.data.accounting.server.value.ItemAccountingCategoryDetailValue; 036import com.echothree.model.data.party.server.entity.Language; 037import com.echothree.util.common.message.ExecutionErrors; 038import com.echothree.util.common.persistence.BasePK; 039import com.echothree.util.server.control.BaseLogic; 040import com.echothree.util.server.message.ExecutionErrorAccumulator; 041import com.echothree.util.server.persistence.EntityPermission; 042import javax.enterprise.context.ApplicationScoped; 043import javax.inject.Inject; 044 045@ApplicationScoped 046public class ItemAccountingCategoryLogic 047 extends BaseLogic { 048 049 @Inject 050 AccountingControl accountingControl; 051 052 @Inject 053 ItemControl itemControl; 054 055 @Inject 056 EntityInstanceLogic entityInstanceLogic; 057 058 @Inject 059 LanguageLogic languageLogic; 060 061 protected ItemAccountingCategoryLogic() { 062 super(); 063 } 064 065 public ItemAccountingCategory createItemAccountingCategory(final ExecutionErrorAccumulator eea, final String itemAccountingCategoryName, 066 final ItemAccountingCategory parentItemAccountingCategory, final GlAccount inventoryGlAccount, final GlAccount salesGlAccount, 067 final GlAccount returnsGlAccount, final GlAccount cogsGlAccount, final GlAccount returnsCogsGlAccount, final Boolean isDefault, 068 final Integer sortOrder, final Language language, final String description, final BasePK createdBy) { 069 var itemAccountingCategory = accountingControl.getItemAccountingCategoryByName(itemAccountingCategoryName); 070 071 if(itemAccountingCategory == null) { 072 itemAccountingCategory = accountingControl.createItemAccountingCategory(itemAccountingCategoryName, 073 parentItemAccountingCategory, inventoryGlAccount, salesGlAccount, returnsGlAccount, cogsGlAccount, 074 returnsCogsGlAccount, isDefault, sortOrder, createdBy); 075 076 if(description != null) { 077 accountingControl.createItemAccountingCategoryDescription(itemAccountingCategory, language, description, createdBy); 078 } 079 } else { 080 handleExecutionError(DuplicateItemAccountingCategoryNameException.class, eea, ExecutionErrors.DuplicateItemAccountingCategoryName.name(), 081 itemAccountingCategoryName); 082 } 083 084 return itemAccountingCategory; 085 } 086 087 public ItemAccountingCategory getItemAccountingCategoryByName(final ExecutionErrorAccumulator eea, final String itemAccountingCategoryName, 088 final EntityPermission entityPermission) { 089 var itemAccountingCategory = accountingControl.getItemAccountingCategoryByName(itemAccountingCategoryName, entityPermission); 090 091 if(itemAccountingCategory == null) { 092 handleExecutionError(UnknownItemAccountingCategoryNameException.class, eea, ExecutionErrors.UnknownItemAccountingCategoryName.name(), itemAccountingCategoryName); 093 } 094 095 return itemAccountingCategory; 096 } 097 098 public ItemAccountingCategory getItemAccountingCategoryByName(final ExecutionErrorAccumulator eea, final String itemAccountingCategoryName) { 099 return getItemAccountingCategoryByName(eea, itemAccountingCategoryName, EntityPermission.READ_ONLY); 100 } 101 102 public ItemAccountingCategory getItemAccountingCategoryByNameForUpdate(final ExecutionErrorAccumulator eea, final String itemAccountingCategoryName) { 103 return getItemAccountingCategoryByName(eea, itemAccountingCategoryName, EntityPermission.READ_WRITE); 104 } 105 106 public ItemAccountingCategory getItemAccountingCategoryByUniversalSpec(final ExecutionErrorAccumulator eea, 107 final ItemAccountingCategoryUniversalSpec universalSpec, boolean allowDefault, final EntityPermission entityPermission) { 108 ItemAccountingCategory itemAccountingCategory = null; 109 var itemAccountingCategoryName = universalSpec.getItemAccountingCategoryName(); 110 var parameterCount = (itemAccountingCategoryName == null ? 0 : 1) + entityInstanceLogic.countPossibleEntitySpecs(universalSpec); 111 112 switch(parameterCount) { 113 case 0 -> { 114 if(allowDefault) { 115 itemAccountingCategory = accountingControl.getDefaultItemAccountingCategory(entityPermission); 116 117 if(itemAccountingCategory == null) { 118 handleExecutionError(UnknownDefaultItemAccountingCategoryException.class, eea, ExecutionErrors.UnknownDefaultItemAccountingCategory.name()); 119 } 120 } else { 121 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 122 } 123 } 124 case 1 -> { 125 if(itemAccountingCategoryName == null) { 126 var entityInstance = entityInstanceLogic.getEntityInstance(eea, universalSpec, 127 ComponentVendors.ECHO_THREE.name(), EntityTypes.ItemAccountingCategory.name()); 128 129 if(eea == null || !eea.hasExecutionErrors()) { 130 itemAccountingCategory = accountingControl.getItemAccountingCategoryByEntityInstance(entityInstance, entityPermission); 131 } 132 } else { 133 itemAccountingCategory = getItemAccountingCategoryByName(eea, itemAccountingCategoryName, entityPermission); 134 } 135 } 136 default -> 137 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 138 } 139 140 return itemAccountingCategory; 141 } 142 143 public ItemAccountingCategory getItemAccountingCategoryByUniversalSpec(final ExecutionErrorAccumulator eea, 144 final ItemAccountingCategoryUniversalSpec universalSpec, boolean allowDefault) { 145 return getItemAccountingCategoryByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_ONLY); 146 } 147 148 public ItemAccountingCategory getItemAccountingCategoryByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, 149 final ItemAccountingCategoryUniversalSpec universalSpec, boolean allowDefault) { 150 return getItemAccountingCategoryByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_WRITE); 151 } 152 153 public ItemAccountingCategoryDescription getItemAccountingCategoryDescriptionBySpec(final ExecutionErrorAccumulator eea, 154 final ItemAccountingCategoryDescriptionSpec spec, final EntityPermission entityPermission) { 155 ItemAccountingCategoryDescription itemAccountingCategoryDescription = null; 156 var itemAccountingCategoryName = spec.getItemAccountingCategoryName(); 157 var itemAccountingCategory = getItemAccountingCategoryByName(eea, itemAccountingCategoryName); 158 159 if(!hasExecutionErrors(eea)) { 160 var languageIsoName = spec.getLanguageIsoName(); 161 var language = languageLogic.getLanguageByName(eea, languageIsoName); 162 163 if(!hasExecutionErrors(eea)) { 164 itemAccountingCategoryDescription = accountingControl.getItemAccountingCategoryDescription(itemAccountingCategory, language, 165 entityPermission); 166 167 if(itemAccountingCategoryDescription == null) { 168 handleExecutionError(UnknownItemAccountingCategoryDescriptionException.class, eea, ExecutionErrors.UnknownItemAccountingCategoryDescription.name(), itemAccountingCategoryName, languageIsoName); 169 } 170 } 171 } 172 173 return itemAccountingCategoryDescription; 174 } 175 176 public void updateItemAccountingCategoryFromValue(ItemAccountingCategoryDetailValue itemAccountingCategoryDetailValue, BasePK updatedBy) { 177 accountingControl.updateItemAccountingCategoryFromValue(itemAccountingCategoryDetailValue, updatedBy); 178 } 179 180 private long countItemsByItemAccountingCategoryChildren(final AccountingControl accountingControl, final ItemControl itemControl, 181 final ItemAccountingCategory parentItemAccountingCategory) { 182 var itemAccountingCategoryChildren = accountingControl.getItemAccountingCategoriesByParentItemAccountingCategory(parentItemAccountingCategory); 183 var total = itemControl.countItemsByItemAccountingCategory(parentItemAccountingCategory); 184 185 total = itemAccountingCategoryChildren.stream().map((childItemAccountingCategory) -> 186 countItemsByItemAccountingCategoryChildren(accountingControl, itemControl, childItemAccountingCategory)).reduce(total, Long::sum); 187 188 return total; 189 } 190 191 private void checkDeleteItemAccountingCategory(final ExecutionErrorAccumulator eea, final ItemAccountingCategory itemAccountingCategory) { 192 if(countItemsByItemAccountingCategoryChildren(accountingControl, itemControl, itemAccountingCategory) != 0) { 193 eea.addExecutionError(ExecutionErrors.CannotDeleteItemAccountingCategoryInUse.name(), 194 itemAccountingCategory.getLastDetail().getItemAccountingCategoryName()); 195 } 196 } 197 198 public void deleteItemAccountingCategory(final ExecutionErrorAccumulator eea, final ItemAccountingCategory itemAccountingCategory, final BasePK deletedBy) { 199 checkDeleteItemAccountingCategory(eea, itemAccountingCategory); 200 201 if(eea == null || !eea.hasExecutionErrors()) { 202 accountingControl.deleteItemAccountingCategory(itemAccountingCategory, deletedBy); 203 } 204 } 205 206}