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