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