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.warehouse.server.logic;
018
019import com.echothree.control.user.core.common.spec.UniversalEntitySpec;
020import com.echothree.control.user.warehouse.common.spec.WarehouseUniversalSpec;
021import com.echothree.model.control.core.common.ComponentVendors;
022import com.echothree.model.control.core.common.EntityTypes;
023import com.echothree.model.control.core.common.exception.InvalidParameterCountException;
024import com.echothree.model.control.core.server.logic.EntityInstanceLogic;
025import com.echothree.model.control.party.common.PartyTypes;
026import com.echothree.model.control.party.common.exception.UnknownPartyNameException;
027import com.echothree.model.control.party.server.control.PartyControl;
028import com.echothree.model.control.party.server.logic.PartyLogic;
029import com.echothree.model.control.warehouse.common.exception.DuplicateWarehouseNameException;
030import com.echothree.model.control.warehouse.common.exception.UnknownDefaultWarehouseException;
031import com.echothree.model.control.warehouse.common.exception.UnknownWarehouseNameException;
032import com.echothree.model.control.warehouse.server.control.WarehouseControl;
033import com.echothree.model.data.accounting.server.entity.Currency;
034import com.echothree.model.data.party.server.entity.DateTimeFormat;
035import com.echothree.model.data.party.server.entity.Language;
036import com.echothree.model.data.party.server.entity.Party;
037import com.echothree.model.data.party.server.entity.TimeZone;
038import com.echothree.model.data.warehouse.server.entity.Warehouse;
039import com.echothree.model.data.warehouse.server.entity.WarehouseType;
040import com.echothree.model.data.warehouse.server.value.WarehouseValue;
041import com.echothree.util.common.message.ExecutionErrors;
042import com.echothree.util.common.persistence.BasePK;
043import com.echothree.util.server.control.BaseLogic;
044import com.echothree.util.server.message.ExecutionErrorAccumulator;
045import com.echothree.util.server.persistence.EntityPermission;
046import javax.enterprise.context.ApplicationScoped;
047import javax.enterprise.inject.spi.CDI;
048import javax.inject.Inject;
049
050@ApplicationScoped
051public class WarehouseLogic
052        extends BaseLogic {
053
054    @Inject
055    PartyControl partyControl;
056
057    @Inject
058    WarehouseControl warehouseControl;
059
060    @Inject
061    EntityInstanceLogic entityInstanceLogic;
062
063    @Inject
064    PartyLogic partyLogic;
065
066    protected WarehouseLogic() {
067        super();
068    }
069
070    public static WarehouseLogic getInstance() {
071        return CDI.current().select(WarehouseLogic.class).get();
072    }
073
074    public Warehouse createWarehouse(final ExecutionErrorAccumulator eea, final String warehouseName, final WarehouseType warehouseType,
075            final Language preferredLanguage, final Currency preferredCurrency, final TimeZone preferredTimeZone,
076            final DateTimeFormat preferredDateTimeFormat, final String name, final Boolean isDefault, final Integer sortOrder,
077            final BasePK createdBy) {
078        var warehouse = warehouseControl.getWarehouseByName(warehouseName);
079
080        if(warehouse == null) {
081            var partyType = partyControl.getPartyTypeByName(PartyTypes.WAREHOUSE.name());
082            var party = partyControl.createParty(null, partyType, preferredLanguage, preferredCurrency,
083                    preferredTimeZone, preferredDateTimeFormat, createdBy);
084
085            if(name != null) {
086                partyControl.createPartyGroup(party, name, createdBy);
087            }
088
089            warehouse = warehouseControl.createWarehouse(party, warehouseName, warehouseType, isDefault, sortOrder, createdBy);
090        } else {
091            handleExecutionError(DuplicateWarehouseNameException.class, eea, ExecutionErrors.DuplicateWarehouseName.name(), warehouseName);
092        }
093
094        return warehouse;
095    }
096
097    public Warehouse getWarehouseByName(final ExecutionErrorAccumulator eea, final String warehouseName, final String partyName,
098            final UniversalEntitySpec universalEntitySpec, final boolean allowDefault, final EntityPermission entityPermission) {
099        Warehouse warehouse = null;
100        var parameterCount = (warehouseName == null ? 0 : 1) + (partyName == null ? 0 : 1) +
101                entityInstanceLogic.countPossibleEntitySpecs(universalEntitySpec);
102
103        switch(parameterCount) {
104            case 0 -> {
105                if(allowDefault) {
106                    warehouse = warehouseControl.getDefaultWarehouse(entityPermission);
107
108                    if(warehouse == null) {
109                        handleExecutionError(UnknownDefaultWarehouseException.class, eea, ExecutionErrors.UnknownDefaultWarehouse.name());
110                    }
111                } else {
112                    handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
113                }
114            }
115            case 1 -> {
116                if(warehouseName != null) {
117                    warehouse = warehouseControl.getWarehouseByName(warehouseName, entityPermission);
118
119                    if(warehouse == null) {
120                        handleExecutionError(UnknownWarehouseNameException.class, eea, ExecutionErrors.UnknownWarehouseName.name(), warehouseName);
121                    }
122                } else if(partyName != null) {
123                    var party = partyControl.getPartyByName(partyName);
124
125                    if(party != null) {
126                        partyLogic.checkPartyType(eea, party, PartyTypes.WAREHOUSE.name());
127
128                        warehouse = warehouseControl.getWarehouse(party, entityPermission);
129                    } else {
130                        handleExecutionError(UnknownPartyNameException.class, eea, ExecutionErrors.UnknownPartyName.name(), partyName);
131                    }
132                } else if(universalEntitySpec != null){
133                    var entityInstance = entityInstanceLogic.getEntityInstance(eea, universalEntitySpec,
134                            ComponentVendors.ECHO_THREE.name(), EntityTypes.Party.name());
135
136                    if(eea == null || !eea.hasExecutionErrors()) {
137                        var party = partyControl.getPartyByEntityInstance(entityInstance);
138
139                        partyLogic.checkPartyType(eea, party, PartyTypes.WAREHOUSE.name());
140
141                        warehouse = warehouseControl.getWarehouse(party, entityPermission);
142                    }
143                }
144            }
145            default ->
146                    handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
147        }
148
149        return warehouse;
150    }
151
152    public Warehouse getWarehouseByName(final ExecutionErrorAccumulator eea, final String warehouseName, final String partyName,
153            final UniversalEntitySpec universalEntitySpec, final boolean allowDefault) {
154        return getWarehouseByName(eea, warehouseName, partyName, universalEntitySpec, allowDefault, EntityPermission.READ_ONLY);
155    }
156
157    public Warehouse getWarehouseByNameForUpdate(final ExecutionErrorAccumulator eea, final String warehouseName, final String partyName,
158            final UniversalEntitySpec universalEntitySpec, final boolean allowDefault) {
159        return getWarehouseByName(eea, warehouseName, partyName, universalEntitySpec, allowDefault, EntityPermission.READ_WRITE);
160    }
161
162    public Warehouse getWarehouseByUniversalSpec(final ExecutionErrorAccumulator eea, final WarehouseUniversalSpec universalSpec,
163            final boolean allowDefault, final EntityPermission entityPermission) {
164        return getWarehouseByName(eea, universalSpec.getWarehouseName(), universalSpec.getPartyName(), universalSpec, allowDefault, entityPermission);
165    }
166
167    public Warehouse getWarehouseByUniversalSpec(final ExecutionErrorAccumulator eea, final WarehouseUniversalSpec universalSpec,
168            final boolean allowDefault) {
169        return getWarehouseByName(eea, universalSpec.getWarehouseName(), universalSpec.getPartyName(), universalSpec, allowDefault);
170    }
171
172    public Warehouse getWarehouseByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, final WarehouseUniversalSpec universalSpec,
173            final boolean allowDefault) {
174        return getWarehouseByNameForUpdate(eea, universalSpec.getWarehouseName(), universalSpec.getPartyName(), universalSpec, allowDefault);
175    }
176
177    public Party getWarehouseParty(final ExecutionErrorAccumulator eea, final String partyName,
178            final String warehouseName) {
179        var warehouse = getWarehouseByName(eea, warehouseName, partyName, null, false);
180
181        return warehouse == null ? null : warehouse.getParty();
182    }
183
184    public void updateWarehouseFromValue(final ExecutionErrorAccumulator eea, final WarehouseValue warehouseValue,
185            final BasePK updatedBy) {
186        warehouseControl.updateWarehouseFromValue(warehouseValue, updatedBy);
187    }
188
189    public void deleteWarehouse(final ExecutionErrorAccumulator eea, final Warehouse warehouse, final BasePK deletedBy) {
190        // TODO: Verify warehouse is empty
191
192        warehouseControl.deleteWarehouse(warehouse, deletedBy);
193    }
194
195}