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