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