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.control.user.inventory.server.command;
018
019import com.echothree.control.user.inventory.common.form.GetInventoryLayersForm;
020import com.echothree.control.user.inventory.common.result.InventoryResultFactory;
021import com.echothree.model.control.inventory.server.control.InventoryCostingPoolControl;
022import com.echothree.model.control.inventory.server.control.InventoryLayerControl;
023import com.echothree.model.control.inventory.server.logic.InventoryCostingPoolLogic;
024import com.echothree.model.control.inventory.server.logic.InventoryTransactionLineLogic;
025import com.echothree.model.control.party.common.PartyTypes;
026import com.echothree.model.control.security.common.SecurityRoleGroups;
027import com.echothree.model.control.security.common.SecurityRoles;
028import com.echothree.model.data.inventory.server.entity.InventoryCostingPool;
029import com.echothree.model.data.inventory.server.entity.InventoryLayer;
030import com.echothree.model.data.inventory.server.entity.InventoryTransactionLine;
031import com.echothree.model.data.inventory.server.factory.InventoryLayerFactory;
032import com.echothree.util.common.command.BaseResult;
033import com.echothree.util.common.message.ExecutionErrors;
034import com.echothree.util.common.validation.FieldDefinition;
035import com.echothree.util.common.validation.FieldType;
036import com.echothree.util.server.control.BasePaginatedMultipleEntitiesCommand;
037import com.echothree.util.server.control.CommandSecurityDefinition;
038import com.echothree.util.server.control.PartyTypeDefinition;
039import com.echothree.util.server.control.SecurityRoleDefinition;
040import com.echothree.util.server.persistence.BaseEntity;
041import java.util.Collection;
042import java.util.List;
043import javax.enterprise.context.Dependent;
044import javax.inject.Inject;
045
046@Dependent
047public class GetInventoryLayersCommand
048        extends BasePaginatedMultipleEntitiesCommand<InventoryLayer, GetInventoryLayersForm> {
049
050    private static final CommandSecurityDefinition COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of(
051            new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
052            new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of(
053                    new SecurityRoleDefinition(SecurityRoleGroups.InventoryLayer.name(), SecurityRoles.List.name())
054            ))
055    ));
056
057    private static final List<FieldDefinition> FORM_FIELD_DEFINITIONS = List.of(
058            new FieldDefinition("PartyName", FieldType.ENTITY_NAME, false, null, null),
059            new FieldDefinition("CompanyName", FieldType.ENTITY_NAME, false, null, null),
060            new FieldDefinition("ItemName", FieldType.ENTITY_NAME, false, null, null),
061            new FieldDefinition("InventoryConditionName", FieldType.ENTITY_NAME, false, null, null),
062            new FieldDefinition("InventoryTransactionTypeName", FieldType.ENTITY_NAME, false, null, null),
063            new FieldDefinition("InventoryTransactionName", FieldType.ENTITY_NAME, false, null, null),
064            new FieldDefinition("InventoryTransactionLineSequence", FieldType.UNSIGNED_INTEGER, false, null, null)
065    );
066
067    @Inject
068    InventoryCostingPoolControl inventoryCostingPoolControl;
069
070    @Inject
071    InventoryLayerControl inventoryLayerControl;
072
073    @Inject
074    InventoryCostingPoolLogic inventoryCostingPoolLogic;
075
076    @Inject
077    InventoryTransactionLineLogic inventoryTransactionLineLogic;
078
079    private BaseEntity filter;
080
081    public GetInventoryLayersCommand() {
082        super(COMMAND_SECURITY_DEFINITION, FORM_FIELD_DEFINITIONS, true);
083    }
084
085    @Override
086    protected void handleForm() {
087        var companyName = form.getCompanyName();
088        var partyName = form.getPartyName();
089        var itemName = form.getItemName();
090        var inventoryConditionName = form.getInventoryConditionName();
091        var inventoryTransactionTypeName = form.getInventoryTransactionTypeName();
092        var inventoryTransactionName = form.getInventoryTransactionName();
093        var inventoryTransactionLineSequence = form.getInventoryTransactionLineSequence();
094        var hasPoolParameters = companyName != null || partyName != null || itemName != null || inventoryConditionName != null;
095        var hasLineParameters = inventoryTransactionTypeName != null || inventoryTransactionName != null || inventoryTransactionLineSequence != null;
096        var hasCompletePool = (companyName != null ^ partyName != null) && itemName != null && inventoryConditionName != null;
097        var hasCompleteLine = inventoryTransactionTypeName != null && inventoryTransactionName != null && inventoryTransactionLineSequence != null;
098
099        if(hasCompletePool && !hasLineParameters) {
100            filter = inventoryCostingPoolLogic.getInventoryCostingPoolByName(this, companyName, partyName, itemName, inventoryConditionName);
101        } else if(hasCompleteLine && !hasPoolParameters) {
102            filter = inventoryTransactionLineLogic.getInventoryTransactionLineBySequence(this, inventoryTransactionTypeName,
103                    inventoryTransactionName, Integer.valueOf(inventoryTransactionLineSequence));
104        } else {
105            addExecutionError(ExecutionErrors.InvalidParameterCount.name());
106        }
107    }
108
109    @Override
110    protected Long getTotalEntities() {
111        if(hasExecutionErrors()) {
112            return null;
113        }
114
115        return switch(filter) {
116            case InventoryCostingPool inventoryCostingPool -> inventoryLayerControl.countInventoryLayersByInventoryCostingPool(inventoryCostingPool);
117            case InventoryTransactionLine inventoryTransactionLine ->
118                    inventoryLayerControl.countInventoryLayersByInventoryTransactionLine(inventoryTransactionLine);
119            default -> throw new IllegalStateException("Unexpected inventory layer filter: " + filter);
120        };
121    }
122
123    @Override
124    protected Collection<InventoryLayer> getEntities() {
125        if(hasExecutionErrors()) {
126            return null;
127        }
128
129        return switch(filter) {
130            case InventoryCostingPool inventoryCostingPool -> inventoryLayerControl.getInventoryLayersByInventoryCostingPool(inventoryCostingPool);
131            case InventoryTransactionLine inventoryTransactionLine -> inventoryLayerControl.getInventoryLayersByInventoryTransactionLine(inventoryTransactionLine);
132            default -> throw new IllegalStateException("Unexpected inventory layer filter: " + filter);
133        };
134    }
135
136    @Override
137    protected BaseResult getResult(Collection<InventoryLayer> entities) {
138        var result = InventoryResultFactory.getGetInventoryLayersResult();
139
140        if(entities != null) {
141            var userVisit = getUserVisit();
142
143            switch(filter) {
144                case InventoryCostingPool inventoryCostingPool ->
145                        result.setInventoryCostingPool(inventoryCostingPoolControl.getInventoryCostingPoolTransfer(userVisit, inventoryCostingPool));
146                case InventoryTransactionLine inventoryTransactionLine -> {
147                    // TODO: Set the InventoryTransactionLineTransfer when transaction-line transfers are implemented.
148                }
149                default -> throw new IllegalStateException("Unexpected inventory layer filter: " + filter);
150            }
151
152            if(session.hasLimit(InventoryLayerFactory.class)) {
153                result.setInventoryLayerCount(getTotalEntities());
154            }
155
156            result.setInventoryLayers(inventoryLayerControl.getInventoryLayerTransfers(userVisit, entities));
157        }
158
159        return result;
160    }
161
162}