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.item.server.command;
018
019import com.echothree.control.user.item.common.edit.ItemEdit;
020import com.echothree.control.user.item.common.edit.ItemEditFactory;
021import com.echothree.control.user.item.common.result.EditItemResult;
022import com.echothree.control.user.item.common.result.ItemResultFactory;
023import com.echothree.control.user.item.common.spec.ItemSpec;
024import com.echothree.model.control.accounting.server.control.AccountingControl;
025import com.echothree.model.control.cancellationpolicy.common.CancellationKinds;
026import com.echothree.model.control.cancellationpolicy.server.control.CancellationPolicyControl;
027import com.echothree.model.control.item.common.ItemTypes;
028import com.echothree.model.control.item.server.control.ItemControl;
029import com.echothree.model.control.party.common.PartyTypes;
030import com.echothree.model.control.returnpolicy.common.ReturnKinds;
031import com.echothree.model.control.returnpolicy.server.control.ReturnPolicyControl;
032import com.echothree.model.control.security.common.SecurityRoleGroups;
033import com.echothree.model.control.security.common.SecurityRoles;
034import com.echothree.model.control.vendor.server.control.VendorControl;
035import com.echothree.model.data.accounting.server.entity.ItemAccountingCategory;
036import com.echothree.model.data.cancellationpolicy.server.entity.CancellationPolicy;
037import com.echothree.model.data.item.server.entity.Item;
038import com.echothree.model.data.item.server.entity.ItemCategory;
039import com.echothree.model.data.returnpolicy.server.entity.ReturnPolicy;
040import com.echothree.model.data.vendor.server.entity.ItemPurchasingCategory;
041import com.echothree.util.common.command.EditMode;
042import com.echothree.util.common.message.ExecutionErrors;
043import com.echothree.util.common.validation.FieldDefinition;
044import com.echothree.util.common.validation.FieldType;
045import com.echothree.util.server.control.BaseAbstractEditCommand;
046import com.echothree.util.server.control.CommandSecurityDefinition;
047import com.echothree.util.server.control.PartyTypeDefinition;
048import com.echothree.util.server.control.SecurityRoleDefinition;
049import com.echothree.util.server.string.DateUtils;
050import java.util.List;
051import javax.enterprise.context.Dependent;
052import javax.inject.Inject;
053
054@Dependent
055public class EditItemCommand
056        extends BaseAbstractEditCommand<ItemSpec, ItemEdit, EditItemResult, Item, Item> {
057    
058    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
059    private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS;
060    private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS;
061    
062    static {
063        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of(
064                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
065                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of(
066                        new SecurityRoleDefinition(SecurityRoleGroups.ItemCategory.name(), SecurityRoles.Edit.name())
067                ))
068        ));
069
070        SPEC_FIELD_DEFINITIONS = List.of(
071                new FieldDefinition("ItemName", FieldType.ENTITY_NAME, true, null, null)
072        );
073        
074        EDIT_FIELD_DEFINITIONS = List.of(
075                new FieldDefinition("ItemName", FieldType.ENTITY_NAME, true, null, null),
076                new FieldDefinition("ItemCategoryName", FieldType.ENTITY_NAME, true, null, null),
077                new FieldDefinition("ItemAccountingCategoryName", FieldType.ENTITY_NAME, false, null, null),
078                new FieldDefinition("ItemPurchasingCategoryName", FieldType.ENTITY_NAME, false, null, null),
079                new FieldDefinition("ShippingChargeExempt", FieldType.BOOLEAN, true, null, null),
080                new FieldDefinition("ShippingStartTime", FieldType.DATE_TIME, false, null, null),
081                new FieldDefinition("ShippingEndTime", FieldType.DATE_TIME, false, null, null),
082                new FieldDefinition("SalesOrderStartTime", FieldType.DATE_TIME, false, null, null),
083                new FieldDefinition("SalesOrderEndTime", FieldType.DATE_TIME, false, null, null),
084                new FieldDefinition("PurchaseOrderStartTime", FieldType.DATE_TIME, false, null, null),
085                new FieldDefinition("PurchaseOrderEndTime", FieldType.DATE_TIME, false, null, null),
086                new FieldDefinition("AllowClubDiscounts", FieldType.BOOLEAN, true, null, null),
087                new FieldDefinition("AllowCouponDiscounts", FieldType.BOOLEAN, true, null, null),
088                new FieldDefinition("AllowAssociatePayments", FieldType.BOOLEAN, true, null, null),
089                new FieldDefinition("CancellationPolicyName", FieldType.ENTITY_NAME, false, null, null),
090                new FieldDefinition("ReturnPolicyName", FieldType.ENTITY_NAME, false, null, null)
091        );
092    }
093
094    @Inject
095    AccountingControl accountingControl;
096
097    @Inject
098    CancellationPolicyControl cancellationPolicyControl;
099
100    @Inject
101    ItemControl itemControl;
102
103    @Inject
104    ReturnPolicyControl returnPolicyControl;
105
106    @Inject
107    VendorControl vendorControl;
108
109    
110    /** Creates a new instance of EditItemCommand */
111    public EditItemCommand() {
112        super(COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS);
113    }
114
115    @Override
116    public EditItemResult getResult() {
117        return ItemResultFactory.getEditItemResult();
118    }
119
120    @Override
121    public ItemEdit getEdit() {
122        return ItemEditFactory.getItemEdit();
123    }
124
125    @Override
126    public Item getEntity(EditItemResult result) {
127        Item item;
128        var itemName = spec.getItemName();
129
130        if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) {
131            item = itemControl.getItemByName(itemName);
132        } else { // EditMode.UPDATE
133            item = itemControl.getItemByNameForUpdate(itemName);
134        }
135
136        if(item != null) {
137            result.setItem(itemControl.getItemTransfer(getUserVisit(), item));
138        } else {
139            addExecutionError(ExecutionErrors.UnknownItemName.name(), itemName);
140        }
141
142        return item;
143    }
144
145    @Override
146    public Item getLockEntity(Item item) {
147        return item;
148    }
149
150    @Override
151    public void fillInResult(EditItemResult result, Item item) {
152        result.setItem(itemControl.getItemTransfer(getUserVisit(), item));
153    }
154
155    @Override
156    public void doLock(ItemEdit edit, Item item) {
157        var dateUtils = DateUtils.getInstance();
158        var itemDetail = item.getLastDetail();
159        var userVisit = getUserVisit();
160        var preferredDateTimeFormat = getPreferredDateTimeFormat();
161
162        itemAccountingCategory = itemDetail.getItemAccountingCategory();
163        itemPurchasingCategory = itemDetail.getItemPurchasingCategory();
164        cancellationPolicy = itemDetail.getCancellationPolicy();
165        returnPolicy = itemDetail.getReturnPolicy();
166
167        edit.setItemName(itemDetail.getItemName());
168        edit.setItemName(edit.getItemName());
169        edit.setItemCategoryName(itemDetail.getItemCategory().getLastDetail().getItemCategoryName());
170        edit.setItemAccountingCategoryName(itemAccountingCategory == null? null: itemAccountingCategory.getLastDetail().getItemAccountingCategoryName());
171        edit.setItemPurchasingCategoryName(itemPurchasingCategory == null? null: itemPurchasingCategory.getLastDetail().getItemPurchasingCategoryName());
172        edit.setShippingChargeExempt(itemDetail.getShippingChargeExempt().toString());
173        edit.setShippingStartTime(dateUtils.formatTypicalDateTime(userVisit, preferredDateTimeFormat, itemDetail.getShippingStartTime()));
174        edit.setShippingEndTime(dateUtils.formatTypicalDateTime(userVisit, preferredDateTimeFormat, itemDetail.getShippingEndTime()));
175        edit.setSalesOrderStartTime(dateUtils.formatTypicalDateTime(userVisit, preferredDateTimeFormat, itemDetail.getSalesOrderStartTime()));
176        edit.setSalesOrderEndTime(dateUtils.formatTypicalDateTime(userVisit, preferredDateTimeFormat, itemDetail.getSalesOrderEndTime()));
177        edit.setPurchaseOrderStartTime(dateUtils.formatTypicalDateTime(userVisit, preferredDateTimeFormat, itemDetail.getPurchaseOrderStartTime()));
178        edit.setPurchaseOrderEndTime(dateUtils.formatTypicalDateTime(userVisit, preferredDateTimeFormat, itemDetail.getPurchaseOrderEndTime()));
179        edit.setAllowClubDiscounts(itemDetail.getAllowClubDiscounts().toString());
180        edit.setAllowCouponDiscounts(itemDetail.getAllowCouponDiscounts().toString());
181        edit.setAllowAssociatePayments(itemDetail.getAllowAssociatePayments().toString());
182        edit.setCancellationPolicyName(cancellationPolicy == null? null: cancellationPolicy.getLastDetail().getCancellationPolicyName());
183        edit.setReturnPolicyName(returnPolicy == null? null: returnPolicy.getLastDetail().getReturnPolicyName());
184    }
185
186    ItemCategory itemCategory;
187    boolean isKit;
188    ItemAccountingCategory itemAccountingCategory;
189    ItemPurchasingCategory itemPurchasingCategory;
190    CancellationPolicy cancellationPolicy;
191    ReturnPolicy returnPolicy;
192
193    @Override
194    public void canUpdate(Item item) {
195        var itemName = edit.getItemName();
196        var duplicateItem = itemControl.getItemByName(itemName);
197
198        if(duplicateItem == null || item.equals(duplicateItem)) {
199            var itemCategoryName = edit.getItemCategoryName();
200            var itemTypeName = item.getLastDetail().getItemType().getItemTypeName();
201
202            itemCategory = itemControl.getItemCategoryByName(itemCategoryName);
203
204            if(itemCategory != null) {
205                var itemAccountingCategoryName = edit.getItemAccountingCategoryName();
206
207                isKit = itemTypeName.equals(ItemTypes.KIT.name());
208
209                if(isKit) {
210                    if(itemAccountingCategoryName != null) {
211                        addExecutionError(ExecutionErrors.NotPermittedItemAccountingCategory.name(), itemAccountingCategoryName);
212                    }
213                } else {
214                    itemAccountingCategory = itemAccountingCategoryName == null? null: accountingControl.getItemAccountingCategoryByName(itemAccountingCategoryName);
215
216                    if(itemAccountingCategoryName == null) {
217                        addExecutionError(ExecutionErrors.MissingItemAccountingCategoryName.name());
218                    } else if(itemAccountingCategory == null) {
219                        addExecutionError(ExecutionErrors.UnknownItemAccountingCategoryName.name(), itemAccountingCategoryName);
220                    }
221                }
222
223                if(!hasExecutionErrors()) {
224                    var itemPurchasingCategoryName = edit.getItemPurchasingCategoryName();
225
226                    if(isKit) {
227                        if(itemPurchasingCategoryName != null) {
228                            addExecutionError(ExecutionErrors.NotPermittedItemPurchasingCategory.name(), itemPurchasingCategoryName);
229                        }
230                    } else {
231                        itemPurchasingCategory = itemPurchasingCategoryName == null? null: vendorControl.getItemPurchasingCategoryByName(itemPurchasingCategoryName);
232
233                        if(itemPurchasingCategoryName == null) {
234                            addExecutionError(ExecutionErrors.MissingItemPurchasingCategoryName.name());
235                        } else if(itemPurchasingCategory == null) {
236                            addExecutionError(ExecutionErrors.UnknownItemPurchasingCategoryName.name(), itemPurchasingCategoryName);
237                        }
238                    }
239
240                    if(!hasExecutionErrors()) {
241                        var cancellationPolicyName = edit.getCancellationPolicyName();
242
243                        if(cancellationPolicyName != null) {
244                            var cancellationKind = cancellationPolicyControl.getCancellationKindByName(CancellationKinds.CUSTOMER_CANCELLATION.name());
245
246                            cancellationPolicy = cancellationPolicyControl.getCancellationPolicyByName(cancellationKind, cancellationPolicyName);
247                        }
248
249                        if(cancellationPolicyName == null || cancellationPolicy != null) {
250                            var returnPolicyName = edit.getReturnPolicyName();
251
252                            if(returnPolicyName != null) {
253                                var returnKind = returnPolicyControl.getReturnKindByName(ReturnKinds.CUSTOMER_RETURN.name());
254
255                                returnPolicy = returnPolicyControl.getReturnPolicyByName(returnKind, returnPolicyName);
256                            }
257
258                            if(returnPolicyName != null && returnPolicy == null) {
259                                addExecutionError(ExecutionErrors.UnknownReturnPolicyName.name(), returnPolicyName);
260                            }
261                        } else {
262                            addExecutionError(ExecutionErrors.UnknownCancellationPolicyName.name(), cancellationPolicyName);
263                        }
264                    }
265                }
266            } else {
267                addExecutionError(ExecutionErrors.UnknownItemCategoryName.name(), itemCategoryName);
268            }
269        } else {
270            addExecutionError(ExecutionErrors.DuplicateItemName.name(), itemName);
271        }
272    }
273
274    @Override
275    public void doUpdate(Item item) {
276        var partyPK = getPartyPK();
277        var itemDetailValue = itemControl.getItemDetailValueForUpdate(item);
278        var shippingChargeExempt = Boolean.valueOf(edit.getShippingChargeExempt());
279        var strShippingStartTime = edit.getShippingStartTime();
280        var shippingStartTime = strShippingStartTime == null? session.getStartTime(): Long.valueOf(strShippingStartTime);
281        var strShippingEndTime = edit.getShippingEndTime();
282        var shippingEndTime = strShippingEndTime == null? null: Long.valueOf(strShippingEndTime);
283        var strSalesOrderStartTime = edit.getSalesOrderStartTime();
284        var salesOrderStartTime = strSalesOrderStartTime == null? session.getStartTime(): Long.valueOf(strSalesOrderStartTime);
285        var strSalesOrderEndTime = edit.getSalesOrderEndTime();
286        var salesOrderEndTime = strSalesOrderEndTime == null? null: Long.valueOf(strSalesOrderEndTime);
287        var strPurchaseOrderStartTime = edit.getPurchaseOrderStartTime();
288        var purchaseOrderStartTime = isKit? null: strPurchaseOrderStartTime == null? session.getStartTime(): Long.valueOf(strPurchaseOrderStartTime);
289        var strPurchaseOrderEndTime = edit.getPurchaseOrderEndTime();
290        var purchaseOrderEndTime = isKit? null: strPurchaseOrderEndTime == null? null: Long.valueOf(strPurchaseOrderEndTime);
291        var allowClubDiscounts = Boolean.valueOf(edit.getAllowClubDiscounts());
292        var allowCouponDiscounts = Boolean.valueOf(edit.getAllowCouponDiscounts());
293        var allowAssociatePayments = Boolean.valueOf(edit.getAllowAssociatePayments());
294
295        itemDetailValue.setItemName(edit.getItemName());
296        itemDetailValue.setItemCategoryPK(itemCategory.getPrimaryKey());
297        itemDetailValue.setItemAccountingCategoryPK(itemAccountingCategory == null? null: itemAccountingCategory.getPrimaryKey());
298        itemDetailValue.setItemPurchasingCategoryPK(itemPurchasingCategory == null? null: itemPurchasingCategory.getPrimaryKey());
299        itemDetailValue.setShippingChargeExempt(shippingChargeExempt);
300        itemDetailValue.setShippingStartTime(shippingStartTime);
301        itemDetailValue.setShippingEndTime(shippingEndTime);
302        itemDetailValue.setSalesOrderStartTime(salesOrderStartTime);
303        itemDetailValue.setSalesOrderEndTime(salesOrderEndTime);
304        itemDetailValue.setPurchaseOrderStartTime(purchaseOrderStartTime);
305        itemDetailValue.setPurchaseOrderEndTime(purchaseOrderEndTime);
306        itemDetailValue.setAllowClubDiscounts(allowClubDiscounts);
307        itemDetailValue.setAllowCouponDiscounts(allowCouponDiscounts);
308        itemDetailValue.setAllowAssociatePayments(allowAssociatePayments);
309        itemDetailValue.setCancellationPolicyPK(cancellationPolicy == null? null: cancellationPolicy.getPrimaryKey());
310        itemDetailValue.setReturnPolicyPK(returnPolicy == null? null: returnPolicy.getPrimaryKey());
311
312        itemControl.updateItemFromValue(itemDetailValue, partyPK);
313    }
314    
315}