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.form.CreateItemForm;
020import com.echothree.control.user.item.common.result.ItemResultFactory;
021import com.echothree.model.control.accounting.server.control.AccountingControl;
022import com.echothree.model.control.cancellationpolicy.common.CancellationKinds;
023import com.echothree.model.control.cancellationpolicy.server.control.CancellationPolicyControl;
024import com.echothree.model.control.core.server.control.EntityInstanceControl;
025import com.echothree.model.control.item.common.workflow.ItemStatusConstants;
026import com.echothree.model.control.item.common.ItemTypes;
027import com.echothree.model.control.item.server.control.ItemControl;
028import com.echothree.model.control.item.server.logic.ItemLogic;
029import com.echothree.model.control.party.common.PartyTypes;
030import com.echothree.model.control.party.server.control.PartyControl;
031import com.echothree.model.control.returnpolicy.common.ReturnKinds;
032import com.echothree.model.control.returnpolicy.server.control.ReturnPolicyControl;
033import com.echothree.model.control.security.common.SecurityRoleGroups;
034import com.echothree.model.control.security.common.SecurityRoles;
035import com.echothree.model.control.uom.server.control.UomControl;
036import com.echothree.model.control.vendor.server.control.VendorControl;
037import com.echothree.model.control.workflow.server.control.WorkflowControl;
038import com.echothree.model.control.workflow.server.logic.WorkflowSecurityLogic;
039import com.echothree.model.data.accounting.server.entity.ItemAccountingCategory;
040import com.echothree.model.data.cancellationpolicy.server.entity.CancellationPolicy;
041import com.echothree.model.data.item.server.entity.ItemDeliveryType;
042import com.echothree.model.data.item.server.entity.ItemInventoryType;
043import com.echothree.model.data.returnpolicy.server.entity.ReturnPolicy;
044import com.echothree.model.data.vendor.server.entity.ItemPurchasingCategory;
045import com.echothree.util.common.command.BaseResult;
046import com.echothree.util.common.message.ExecutionErrors;
047import com.echothree.util.common.validation.FieldDefinition;
048import com.echothree.util.common.validation.FieldType;
049import com.echothree.util.server.control.BaseSimpleCommand;
050import com.echothree.util.server.control.CommandSecurityDefinition;
051import com.echothree.util.server.control.PartyTypeDefinition;
052import com.echothree.util.server.control.SecurityRoleDefinition;
053import com.echothree.util.server.persistence.Session;
054import java.util.List;
055import javax.enterprise.context.Dependent;
056
057@Dependent
058public class CreateItemCommand
059        extends BaseSimpleCommand<CreateItemForm> {
060    
061    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
062    private final static List<FieldDefinition> FORM_FIELD_DEFINITIONS;
063    
064    static {
065        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of(
066                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
067                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of(
068                        new SecurityRoleDefinition(SecurityRoleGroups.ItemCategory.name(), SecurityRoles.Create.name())
069                        ))
070                ));
071
072        FORM_FIELD_DEFINITIONS = List.of(
073                new FieldDefinition("ItemName", FieldType.ENTITY_NAME, false, null, null),
074                new FieldDefinition("ItemTypeName", FieldType.ENTITY_NAME, true, null, null),
075                new FieldDefinition("ItemUseTypeName", FieldType.ENTITY_NAME, true, null, null),
076                new FieldDefinition("ItemCategoryName", FieldType.ENTITY_NAME, false, 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("CompanyName", FieldType.ENTITY_NAME, true, null, null),
080                new FieldDefinition("ItemDeliveryTypeName", FieldType.ENTITY_NAME, false, null, null),
081                new FieldDefinition("ItemInventoryTypeName", FieldType.ENTITY_NAME, false, null, null),
082                new FieldDefinition("InventorySerialized", FieldType.BOOLEAN, false, null, null),
083                new FieldDefinition("ShippingChargeExempt", FieldType.BOOLEAN, true, null, null),
084                new FieldDefinition("ShippingStartTime", FieldType.DATE_TIME, false, null, null),
085                new FieldDefinition("ShippingEndTime", FieldType.DATE_TIME, false, null, null),
086                new FieldDefinition("SalesOrderStartTime", FieldType.DATE_TIME, false, null, null),
087                new FieldDefinition("SalesOrderEndTime", FieldType.DATE_TIME, false, null, null),
088                new FieldDefinition("PurchaseOrderStartTime", FieldType.DATE_TIME, false, null, null),
089                new FieldDefinition("PurchaseOrderEndTime", FieldType.DATE_TIME, false, null, null),
090                new FieldDefinition("AllowClubDiscounts", FieldType.BOOLEAN, true, null, null),
091                new FieldDefinition("AllowCouponDiscounts", FieldType.BOOLEAN, true, null, null),
092                new FieldDefinition("AllowAssociatePayments", FieldType.BOOLEAN, true, null, null),
093                new FieldDefinition("ItemStatus", FieldType.ENTITY_NAME, true, null, null),
094                new FieldDefinition("UnitOfMeasureKindName", FieldType.ENTITY_NAME, true, null, null),
095                new FieldDefinition("ItemPriceTypeName", FieldType.ENTITY_NAME, true, null, null),
096                new FieldDefinition("CancellationPolicyName", FieldType.ENTITY_NAME, false, null, null),
097                new FieldDefinition("ReturnPolicyName", FieldType.ENTITY_NAME, false, null, null)
098                );
099    }
100    
101    /** Creates a new instance of CreateItemCommand */
102    public CreateItemCommand() {
103        super(COMMAND_SECURITY_DEFINITION, FORM_FIELD_DEFINITIONS, false);
104    }
105    
106    @Override
107    protected BaseResult execute() {
108        var result = ItemResultFactory.getCreateItemResult();
109        var itemControl = Session.getModelController(ItemControl.class);
110        var itemName = form.getItemName();
111        var item = itemName == null ? null : itemControl.getItemByNameThenAlias(itemName);
112        
113        if(item == null) {
114            var itemTypeName = form.getItemTypeName();
115            var itemType = itemControl.getItemTypeByName(itemTypeName);
116            
117            if(itemType != null) {
118                var itemUseTypeName = form.getItemUseTypeName();
119                var itemUseType = itemControl.getItemUseTypeByName(itemUseTypeName);
120                    
121                itemTypeName = itemType.getItemTypeName();
122                
123                if(itemUseType != null) {
124                    var itemCategoryName = form.getItemCategoryName();
125                    var itemCategory = itemCategoryName == null ? null : itemControl.getItemCategoryByName(itemCategoryName);
126                    
127                    if(itemCategoryName == null || itemCategory != null) {
128                        var isKitOrStyle = itemTypeName.equals(ItemTypes.KIT.name())
129                                || itemTypeName.equals(ItemTypes.STYLE.name());
130                        var itemAccountingCategoryName = form.getItemAccountingCategoryName();
131                        ItemAccountingCategory itemAccountingCategory = null;
132                        
133                        if(isKitOrStyle) {
134                            if(itemAccountingCategoryName != null) {
135                                addExecutionError(ExecutionErrors.NotPermittedItemAccountingCategory.name(), itemAccountingCategoryName);
136                            }
137                        } else {
138                            var accountingControl = Session.getModelController(AccountingControl.class);
139                            
140                            itemAccountingCategory = itemAccountingCategoryName == null? null: accountingControl.getItemAccountingCategoryByName(itemAccountingCategoryName);
141                            
142                            if(itemAccountingCategoryName == null) {
143                                addExecutionError(ExecutionErrors.MissingItemAccountingCategoryName.name());
144                            } else if(itemAccountingCategory == null) {
145                                addExecutionError(ExecutionErrors.UnknownItemAccountingCategoryName.name(), itemAccountingCategoryName);
146                            }
147                        }
148                        
149                        if(!hasExecutionErrors()) {
150                            var itemPurchasingCategoryName = form.getItemPurchasingCategoryName();
151                            ItemPurchasingCategory itemPurchasingCategory = null;
152                            
153                            if(isKitOrStyle) {
154                                if(itemPurchasingCategoryName != null) {
155                                    addExecutionError(ExecutionErrors.NotPermittedItemPurchasingCategory.name(), itemPurchasingCategoryName);
156                                }
157                            } else {
158                                var vendorControl = Session.getModelController(VendorControl.class);
159                                
160                                itemPurchasingCategory = itemPurchasingCategoryName == null? null: vendorControl.getItemPurchasingCategoryByName(itemPurchasingCategoryName);
161                                
162                                if(itemPurchasingCategoryName == null) {
163                                    addExecutionError(ExecutionErrors.MissingItemPurchasingCategoryName.name());
164                                } else if(itemPurchasingCategory == null) {
165                                    addExecutionError(ExecutionErrors.UnknownItemPurchasingCategoryName.name(), itemPurchasingCategoryName);
166                                }
167                            }
168                            
169                            if(!hasExecutionErrors()) {
170                                var partyControl = Session.getModelController(PartyControl.class);
171                                var companyName = form.getCompanyName();
172                                var partyCompany = partyControl.getPartyCompanyByName(companyName);
173                                
174                                if(partyCompany != null) {
175                                    var itemDeliveryTypeName = form.getItemDeliveryTypeName();
176                                    ItemDeliveryType itemDeliveryType = null;
177                                    
178                                    if(isKitOrStyle) {
179                                        if(itemDeliveryTypeName != null) {
180                                            addExecutionError(ExecutionErrors.NotPermittedItemDeliveryType.name(), itemDeliveryTypeName);
181                                        }
182                                    } else {
183                                        itemDeliveryType = itemDeliveryTypeName == null? null: itemControl.getItemDeliveryTypeByName(itemDeliveryTypeName);
184                                        
185                                        if(itemDeliveryTypeName == null) {
186                                            addExecutionError(ExecutionErrors.MissingItemDeliveryTypeName.name());
187                                        } else if(itemDeliveryType == null) {
188                                            addExecutionError(ExecutionErrors.UnknownItemDeliveryTypeName.name(), itemDeliveryTypeName);
189                                        }
190                                    }
191                                    
192                                    if(!hasExecutionErrors()) {
193                                        var itemInventoryTypeName = form.getItemInventoryTypeName();
194                                        ItemInventoryType itemInventoryType = null;
195
196                                        if(isKitOrStyle) {
197                                            if(itemInventoryTypeName != null) {
198                                                addExecutionError(ExecutionErrors.NotPermittedItemInventoryType.name(), itemInventoryTypeName);
199                                            }
200                                        } else {
201                                            itemInventoryType = itemInventoryTypeName == null? null: itemControl.getItemInventoryTypeByName(itemInventoryTypeName);
202
203                                            if(itemInventoryTypeName == null) {
204                                                addExecutionError(ExecutionErrors.MissingItemInventoryTypeName.name());
205                                            } else if(itemInventoryType == null) {
206                                                addExecutionError(ExecutionErrors.UnknownItemInventoryTypeName.name(), itemInventoryTypeName);
207                                            }
208                                        }
209
210                                        if(!hasExecutionErrors()) {
211                                            var uomControl = Session.getModelController(UomControl.class);
212                                            var unitOfMeasureKindName = form.getUnitOfMeasureKindName();
213                                            var unitOfMeasureKind = uomControl.getUnitOfMeasureKindByName(unitOfMeasureKindName);
214
215                                            if(unitOfMeasureKind != null) {
216                                                var itemPriceTypeName = form.getItemPriceTypeName();
217                                                var itemPriceType = itemControl.getItemPriceTypeByName(itemPriceTypeName);
218
219                                                if(itemPriceType != null) {
220                                                    var cancellationPolicyName = form.getCancellationPolicyName();
221                                                    CancellationPolicy cancellationPolicy = null;
222
223                                                    if(cancellationPolicyName != null) {
224                                                        var cancellationPolicyControl = Session.getModelController(CancellationPolicyControl.class);
225                                                        var cancellationKind = cancellationPolicyControl.getCancellationKindByName(CancellationKinds.CUSTOMER_CANCELLATION.name());
226
227                                                        cancellationPolicy = cancellationPolicyControl.getCancellationPolicyByName(cancellationKind, cancellationPolicyName);
228                                                    }
229
230                                                    if(cancellationPolicyName == null || cancellationPolicy != null) {
231                                                        var returnPolicyName = form.getReturnPolicyName();
232                                                        ReturnPolicy returnPolicy = null;
233
234                                                        if(returnPolicyName != null) {
235                                                            var returnPolicyControl = Session.getModelController(ReturnPolicyControl.class);
236                                                            var returnKind = returnPolicyControl.getReturnKindByName(ReturnKinds.CUSTOMER_RETURN.name());
237
238                                                            returnPolicy = returnPolicyControl.getReturnPolicyByName(returnKind, returnPolicyName);
239                                                        }
240
241                                                        if(returnPolicyName == null || returnPolicy != null) {
242                                                            var rawInventorySerialized = form.getInventorySerialized();
243                                                            var inventorySerialized = rawInventorySerialized == null? null: Boolean.valueOf(rawInventorySerialized);
244
245                                                            if(isKitOrStyle ? inventorySerialized == null : inventorySerialized != null) {
246                                                                var workflowControl = Session.getModelController(WorkflowControl.class);
247                                                                var itemStatusChoice = form.getItemStatus();
248                                                                var itemStatus = workflowControl.getWorkflowEntranceUsingNames(this, ItemStatusConstants.Workflow_ITEM_STATUS,
249                                                                        itemStatusChoice);
250                                                                var createdBy = getPartyPK();
251
252                                                                if(!hasExecutionErrors() && WorkflowSecurityLogic.getInstance().checkAddEntityToWorkflow(this, itemStatus, createdBy)) {
253                                                                    var shippingChargeExempt = Boolean.valueOf(form.getShippingChargeExempt());
254                                                                    var strShippingStartTime = form.getShippingStartTime();
255                                                                    var shippingStartTime = strShippingStartTime == null ? session.getStartTime() : Long.valueOf(strShippingStartTime);
256                                                                    var strShippingEndTime = form.getShippingEndTime();
257                                                                    var shippingEndTime = strShippingEndTime == null ? null : Long.valueOf(strShippingEndTime);
258                                                                    var strSalesOrderStartTime = form.getSalesOrderStartTime();
259                                                                    var salesOrderStartTime = strSalesOrderStartTime == null ? session.getStartTime() : Long.valueOf(strSalesOrderStartTime);
260                                                                    var strSalesOrderEndTime = form.getSalesOrderEndTime();
261                                                                    var salesOrderEndTime = strSalesOrderEndTime == null ? null : Long.valueOf(strSalesOrderEndTime);
262                                                                    var strPurchaseOrderStartTime = form.getPurchaseOrderStartTime();
263                                                                    var purchaseOrderStartTime = isKitOrStyle ? null : strPurchaseOrderStartTime == null ? session.getStartTime() : Long.valueOf(strPurchaseOrderStartTime);
264                                                                    var strPurchaseOrderEndTime = form.getPurchaseOrderEndTime();
265                                                                    var purchaseOrderEndTime = isKitOrStyle ? null : strPurchaseOrderEndTime == null ? null : Long.valueOf(strPurchaseOrderEndTime);
266                                                                    var allowClubDiscounts = Boolean.valueOf(form.getAllowClubDiscounts());
267                                                                    var allowCouponDiscounts = Boolean.valueOf(form.getAllowCouponDiscounts());
268                                                                    var allowAssociatePayments = Boolean.valueOf(form.getAllowAssociatePayments());
269
270                                                                    // TODO: SerialNumberSequenceName is currently ignored.
271                                                                    item = ItemLogic.getInstance().createItem(this, itemName, itemType, itemUseType, itemCategory,
272                                                                            itemAccountingCategory, itemPurchasingCategory, partyCompany.getParty(),
273                                                                            itemDeliveryType, itemInventoryType, inventorySerialized, null, shippingChargeExempt,
274                                                                            shippingStartTime, shippingEndTime, salesOrderStartTime, salesOrderEndTime,
275                                                                            purchaseOrderStartTime, purchaseOrderEndTime, allowClubDiscounts, allowCouponDiscounts,
276                                                                            allowAssociatePayments, unitOfMeasureKind, itemPriceType, cancellationPolicy,
277                                                                            returnPolicy, null, createdBy);
278
279                                                                    if(!hasExecutionErrors()) {
280                                                                        var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
281                                                                        var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(item.getPrimaryKey());
282
283                                                                        workflowControl.addEntityToWorkflow(itemStatus, entityInstance, null, null, createdBy);
284                                                                    }
285                                                                }
286                                                            } else {
287                                                                if(isKitOrStyle) {
288                                                                    if(inventorySerialized != null) {
289                                                                        addExecutionError(ExecutionErrors.NotPermittedInventorySerialized.name());
290                                                                    }
291                                                                } else {
292                                                                    if(inventorySerialized == null) {
293                                                                        addExecutionError(ExecutionErrors.MissingInventorySerialized.name());
294                                                                    }
295                                                                }
296                                                            }
297                                                        } else {
298                                                            addExecutionError(ExecutionErrors.UnknownReturnPolicyName.name(), returnPolicyName);
299                                                        }
300                                                    } else {
301                                                        addExecutionError(ExecutionErrors.UnknownCancellationPolicyName.name(), cancellationPolicyName);
302                                                    }
303                                                } else {
304                                                    addExecutionError(ExecutionErrors.UnknownItemPriceTypeName.name(), itemPriceTypeName);
305                                                }
306                                            } else {
307                                                addExecutionError(ExecutionErrors.UnknownUnitOfMeasureKindName.name(), unitOfMeasureKindName);
308                                            }
309                                        }
310                                    }
311                                } else {
312                                    addExecutionError(ExecutionErrors.UnknownCompanyName.name(), companyName);
313                                }
314                            }
315                        }
316                    } else {
317                        addExecutionError(ExecutionErrors.UnknownItemCategoryName.name(), itemCategoryName);
318                    }
319                } else {
320                    addExecutionError(ExecutionErrors.UnknownItemUseTypeName.name(), itemUseTypeName);
321                }
322            } else {
323                addExecutionError(ExecutionErrors.UnknownItemTypeName.name(), itemTypeName);
324            }
325        } else {
326            addExecutionError(ExecutionErrors.DuplicateItemName.name(), itemName);
327        }
328        
329        if(item != null) {
330            result.setItemName(item.getLastDetail().getItemName());
331            result.setEntityRef(item.getPrimaryKey().getEntityRef());
332        }
333        
334        return result;
335    }
336    
337}