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.sales.server.command;
018
019import com.echothree.control.user.sales.common.edit.SalesEditFactory;
020import com.echothree.control.user.sales.common.edit.SalesOrderBatchEdit;
021import com.echothree.control.user.sales.common.form.EditSalesOrderBatchForm;
022import com.echothree.control.user.sales.common.result.EditSalesOrderBatchResult;
023import com.echothree.control.user.sales.common.result.SalesResultFactory;
024import com.echothree.control.user.sales.common.spec.SalesOrderBatchSpec;
025import com.echothree.model.control.accounting.server.control.AccountingControl;
026import com.echothree.model.control.order.server.control.OrderBatchControl;
027import com.echothree.model.control.party.common.PartyTypes;
028import com.echothree.model.control.payment.server.control.PaymentMethodControl;
029import com.echothree.model.control.sales.server.control.SalesOrderBatchControl;
030import com.echothree.model.control.sales.server.logic.SalesOrderBatchLogic;
031import com.echothree.model.control.security.common.SecurityRoleGroups;
032import com.echothree.model.control.security.common.SecurityRoles;
033import com.echothree.model.data.accounting.server.entity.Currency;
034import com.echothree.model.data.batch.server.entity.Batch;
035import com.echothree.model.data.payment.server.entity.PaymentMethod;
036import com.echothree.model.data.user.common.pk.UserVisitPK;
037import com.echothree.util.common.command.EditMode;
038import com.echothree.util.common.message.ExecutionErrors;
039import com.echothree.util.common.validation.FieldDefinition;
040import com.echothree.util.common.validation.FieldType;
041import com.echothree.util.server.control.BaseAbstractEditCommand;
042import com.echothree.util.server.control.CommandSecurityDefinition;
043import com.echothree.util.server.control.PartyTypeDefinition;
044import com.echothree.util.server.control.SecurityRoleDefinition;
045import com.echothree.util.server.string.AmountUtils;
046import java.util.List;
047import javax.enterprise.context.Dependent;
048import javax.inject.Inject;
049
050@Dependent
051public class EditSalesOrderBatchCommand
052        extends BaseAbstractEditCommand<SalesOrderBatchSpec, SalesOrderBatchEdit, EditSalesOrderBatchResult, Batch, Batch> {
053
054    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
055    private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS;
056    private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS;
057
058    static {
059        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of(
060                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
061                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of(
062                        new SecurityRoleDefinition(SecurityRoleGroups.SalesOrderBatch.name(), SecurityRoles.Edit.name())
063                ))
064        ));
065
066        SPEC_FIELD_DEFINITIONS = List.of(
067                new FieldDefinition("BatchName", FieldType.ENTITY_NAME, true, null, null)
068        );
069
070        EDIT_FIELD_DEFINITIONS = List.of(
071                new FieldDefinition("CurrencyIsoName", FieldType.ENTITY_NAME, true, null, null),
072                new FieldDefinition("PaymentMethodName", FieldType.ENTITY_NAME, true, null, null),
073                new FieldDefinition("Count", FieldType.UNSIGNED_LONG, false, null, null),
074                new FieldDefinition("Amount:CurrencyIsoName,CurrencyIsoName", FieldType.UNSIGNED_PRICE_LINE, false, null, null)
075        );
076    }
077
078    @Inject
079    AccountingControl accountingControl;
080
081    @Inject
082    OrderBatchControl orderBatchControl;
083
084    @Inject
085    PaymentMethodControl paymentMethodControl;
086
087    @Inject
088    SalesOrderBatchControl salesOrderBatchControl;
089
090    @Inject
091    SalesOrderBatchLogic salesOrderBatchLogic;
092
093    /** Creates a new instance of EditSalesOrderBatchCommand */
094    public EditSalesOrderBatchCommand() {
095        super(COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS);
096    }
097
098    @Override
099    public EditSalesOrderBatchResult getResult() {
100        return SalesResultFactory.getEditSalesOrderBatchResult();
101    }
102
103    @Override
104    public SalesOrderBatchEdit getEdit() {
105        return SalesEditFactory.getSalesOrderBatchEdit();
106    }
107
108    @Override
109    public Batch getEntity(EditSalesOrderBatchResult result) {
110        Batch batch;
111        var batchName = spec.getBatchName();
112
113        if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) {
114            batch = salesOrderBatchLogic.getBatchByName(this, batchName);
115        } else { // EditMode.UPDATE
116            batch = salesOrderBatchLogic.getBatchByNameForUpdate(this, batchName);
117        }
118
119        if(!hasExecutionErrors()) {
120            result.setSalesOrderBatch(salesOrderBatchControl.getSalesOrderBatchTransfer(getUserVisit(), batch));
121        }
122
123        return batch;
124    }
125
126    @Override
127    public Batch getLockEntity(Batch batch) {
128        return batch;
129    }
130
131    @Override
132    public void fillInResult(EditSalesOrderBatchResult result, Batch batch) {
133        result.setSalesOrderBatch(salesOrderBatchControl.getSalesOrderBatchTransfer(getUserVisit(), batch));
134    }
135
136    @Override
137    public void doLock(SalesOrderBatchEdit edit, Batch batch) {
138        var orderBatch = orderBatchControl.getOrderBatch(batch);
139        var salesOrderBatch = salesOrderBatchControl.getSalesOrderBatch(batch);
140        var count = orderBatch.getCount();
141
142        // TODO: currency and payment method should be editable only if the batch has no orders in it.
143        edit.setCurrencyIsoName(orderBatch.getCurrency().getCurrencyIsoName());
144        edit.setPaymentMethodName(salesOrderBatch.getPaymentMethod().getLastDetail().getPaymentMethodName());
145        edit.setCount(count == null ? null : count.toString());
146        edit.setAmount(AmountUtils.getInstance().formatCostUnit(orderBatch.getCurrency(), orderBatch.getAmount()));
147    }
148
149     Currency currency;
150     PaymentMethod paymentMethod;
151
152    @Override
153    public void canUpdate(Batch batch) {
154        // TODO: currency and payment method should be checked only if the batch has no orders in it.
155        var currencyIsoName = edit.getCurrencyIsoName();
156
157        currency = accountingControl.getCurrencyByIsoName(currencyIsoName);
158
159        if(currency != null) {
160            var paymentMethodName = edit.getPaymentMethodName();
161
162            paymentMethod = paymentMethodControl.getPaymentMethodByName(paymentMethodName);
163
164            if(paymentMethod == null) {
165                addExecutionError(ExecutionErrors.UnknownPaymentMethodName.name(), paymentMethodName);
166            }
167        } else {
168            addExecutionError(ExecutionErrors.UnknownCurrencyIsoName.name(), currencyIsoName);
169        }
170    }
171
172    @Override
173    public void doUpdate(Batch batch) {
174        var partyPK = getPartyPK();
175        var strCount = edit.getCount();
176        var count = strCount == null ? null : Long.valueOf(strCount);
177        var strAmount = edit.getAmount();
178        var amount = strAmount == null ? null : Long.valueOf(strAmount);
179        var orderBatchValue = orderBatchControl.getOrderBatchValueForUpdate(batch);
180        var salesOrderBatchValue = salesOrderBatchControl.getSalesOrderBatchValueForUpdate(batch);
181
182        if(currency != null) {
183            orderBatchValue.setCurrencyPK(currency.getPrimaryKey());
184        }
185        orderBatchValue.setCount(count);
186        orderBatchValue.setAmount(amount);
187        if(paymentMethod != null) {
188            salesOrderBatchValue.setPaymentMethodPK(paymentMethod.getPrimaryKey());
189        }
190
191        orderBatchControl.updateOrderBatchFromValue(orderBatchValue, partyPK);
192        salesOrderBatchControl.updateSalesOrderBatchFromValue(salesOrderBatchValue, partyPK);
193    }
194
195}