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