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 java.util.List;
054import javax.enterprise.context.Dependent;
055import javax.inject.Inject;
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    @Inject
102    AccountingControl accountingControl;
103
104    @Inject
105    CancellationPolicyControl cancellationPolicyControl;
106
107    @Inject
108    EntityInstanceControl entityInstanceControl;
109
110    @Inject
111    ItemControl itemControl;
112
113    @Inject
114    PartyControl partyControl;
115
116    @Inject
117    ReturnPolicyControl returnPolicyControl;
118
119    @Inject
120    UomControl uomControl;
121
122    @Inject
123    VendorControl vendorControl;
124
125    @Inject
126    WorkflowControl workflowControl;
127
128    @Inject
129    ItemLogic itemLogic;
130
131    @Inject
132    WorkflowSecurityLogic workflowSecurityLogic;
133
134    
135    /** Creates a new instance of CreateItemCommand */
136    public CreateItemCommand() {
137        super(COMMAND_SECURITY_DEFINITION, FORM_FIELD_DEFINITIONS, false);
138    }
139    
140    @Override
141    protected BaseResult execute() {
142        var result = ItemResultFactory.getCreateItemResult();
143        var itemName = form.getItemName();
144        var item = itemName == null ? null : itemControl.getItemByNameThenAlias(itemName);
145        
146        if(item == null) {
147            var itemTypeName = form.getItemTypeName();
148            var itemType = itemControl.getItemTypeByName(itemTypeName);
149            
150            if(itemType != null) {
151                var itemUseTypeName = form.getItemUseTypeName();
152                var itemUseType = itemControl.getItemUseTypeByName(itemUseTypeName);
153                    
154                itemTypeName = itemType.getItemTypeName();
155                
156                if(itemUseType != null) {
157                    var itemCategoryName = form.getItemCategoryName();
158                    var itemCategory = itemCategoryName == null ? null : itemControl.getItemCategoryByName(itemCategoryName);
159                    
160                    if(itemCategoryName == null || itemCategory != null) {
161                        var isKitOrStyle = itemTypeName.equals(ItemTypes.KIT.name())
162                                || itemTypeName.equals(ItemTypes.STYLE.name());
163                        var itemAccountingCategoryName = form.getItemAccountingCategoryName();
164                        ItemAccountingCategory itemAccountingCategory = null;
165                        
166                        if(isKitOrStyle) {
167                            if(itemAccountingCategoryName != null) {
168                                addExecutionError(ExecutionErrors.NotPermittedItemAccountingCategory.name(), itemAccountingCategoryName);
169                            }
170                        } else {
171                            itemAccountingCategory = itemAccountingCategoryName == null? null: accountingControl.getItemAccountingCategoryByName(itemAccountingCategoryName);
172                            
173                            if(itemAccountingCategoryName == null) {
174                                addExecutionError(ExecutionErrors.MissingItemAccountingCategoryName.name());
175                            } else if(itemAccountingCategory == null) {
176                                addExecutionError(ExecutionErrors.UnknownItemAccountingCategoryName.name(), itemAccountingCategoryName);
177                            }
178                        }
179                        
180                        if(!hasExecutionErrors()) {
181                            var itemPurchasingCategoryName = form.getItemPurchasingCategoryName();
182                            ItemPurchasingCategory itemPurchasingCategory = null;
183                            
184                            if(isKitOrStyle) {
185                                if(itemPurchasingCategoryName != null) {
186                                    addExecutionError(ExecutionErrors.NotPermittedItemPurchasingCategory.name(), itemPurchasingCategoryName);
187                                }
188                            } else {
189                                itemPurchasingCategory = itemPurchasingCategoryName == null? null: vendorControl.getItemPurchasingCategoryByName(itemPurchasingCategoryName);
190                                
191                                if(itemPurchasingCategoryName == null) {
192                                    addExecutionError(ExecutionErrors.MissingItemPurchasingCategoryName.name());
193                                } else if(itemPurchasingCategory == null) {
194                                    addExecutionError(ExecutionErrors.UnknownItemPurchasingCategoryName.name(), itemPurchasingCategoryName);
195                                }
196                            }
197                            
198                            if(!hasExecutionErrors()) {
199                                var companyName = form.getCompanyName();
200                                var partyCompany = partyControl.getPartyCompanyByName(companyName);
201                                
202                                if(partyCompany != null) {
203                                    var itemDeliveryTypeName = form.getItemDeliveryTypeName();
204                                    ItemDeliveryType itemDeliveryType = null;
205                                    
206                                    if(isKitOrStyle) {
207                                        if(itemDeliveryTypeName != null) {
208                                            addExecutionError(ExecutionErrors.NotPermittedItemDeliveryType.name(), itemDeliveryTypeName);
209                                        }
210                                    } else {
211                                        itemDeliveryType = itemDeliveryTypeName == null? null: itemControl.getItemDeliveryTypeByName(itemDeliveryTypeName);
212                                        
213                                        if(itemDeliveryTypeName == null) {
214                                            addExecutionError(ExecutionErrors.MissingItemDeliveryTypeName.name());
215                                        } else if(itemDeliveryType == null) {
216                                            addExecutionError(ExecutionErrors.UnknownItemDeliveryTypeName.name(), itemDeliveryTypeName);
217                                        }
218                                    }
219                                    
220                                    if(!hasExecutionErrors()) {
221                                        var itemInventoryTypeName = form.getItemInventoryTypeName();
222                                        ItemInventoryType itemInventoryType = null;
223
224                                        if(isKitOrStyle) {
225                                            if(itemInventoryTypeName != null) {
226                                                addExecutionError(ExecutionErrors.NotPermittedItemInventoryType.name(), itemInventoryTypeName);
227                                            }
228                                        } else {
229                                            itemInventoryType = itemInventoryTypeName == null? null: itemControl.getItemInventoryTypeByName(itemInventoryTypeName);
230
231                                            if(itemInventoryTypeName == null) {
232                                                addExecutionError(ExecutionErrors.MissingItemInventoryTypeName.name());
233                                            } else if(itemInventoryType == null) {
234                                                addExecutionError(ExecutionErrors.UnknownItemInventoryTypeName.name(), itemInventoryTypeName);
235                                            }
236                                        }
237
238                                        if(!hasExecutionErrors()) {
239                                            var unitOfMeasureKindName = form.getUnitOfMeasureKindName();
240                                            var unitOfMeasureKind = uomControl.getUnitOfMeasureKindByName(unitOfMeasureKindName);
241
242                                            if(unitOfMeasureKind != null) {
243                                                var itemPriceTypeName = form.getItemPriceTypeName();
244                                                var itemPriceType = itemControl.getItemPriceTypeByName(itemPriceTypeName);
245
246                                                if(itemPriceType != null) {
247                                                    var cancellationPolicyName = form.getCancellationPolicyName();
248                                                    CancellationPolicy cancellationPolicy = null;
249
250                                                    if(cancellationPolicyName != null) {
251                                                        var cancellationKind = cancellationPolicyControl.getCancellationKindByName(CancellationKinds.CUSTOMER_CANCELLATION.name());
252
253                                                        cancellationPolicy = cancellationPolicyControl.getCancellationPolicyByName(cancellationKind, cancellationPolicyName);
254                                                    }
255
256                                                    if(cancellationPolicyName == null || cancellationPolicy != null) {
257                                                        var returnPolicyName = form.getReturnPolicyName();
258                                                        ReturnPolicy returnPolicy = null;
259
260                                                        if(returnPolicyName != null) {
261                                                            var returnKind = returnPolicyControl.getReturnKindByName(ReturnKinds.CUSTOMER_RETURN.name());
262
263                                                            returnPolicy = returnPolicyControl.getReturnPolicyByName(returnKind, returnPolicyName);
264                                                        }
265
266                                                        if(returnPolicyName == null || returnPolicy != null) {
267                                                            var rawInventorySerialized = form.getInventorySerialized();
268                                                            var inventorySerialized = rawInventorySerialized == null? null: Boolean.valueOf(rawInventorySerialized);
269
270                                                            if(isKitOrStyle ? inventorySerialized == null : inventorySerialized != null) {
271                                                                var itemStatusChoice = form.getItemStatus();
272                                                                var itemStatus = workflowControl.getWorkflowEntranceUsingNames(this, ItemStatusConstants.Workflow_ITEM_STATUS,
273                                                                        itemStatusChoice);
274                                                                var createdBy = getPartyPK();
275
276                                                                if(!hasExecutionErrors() && workflowSecurityLogic.checkAddEntityToWorkflow(this, itemStatus, createdBy)) {
277                                                                    var shippingChargeExempt = Boolean.valueOf(form.getShippingChargeExempt());
278                                                                    var strShippingStartTime = form.getShippingStartTime();
279                                                                    var shippingStartTime = strShippingStartTime == null ? session.getStartTime() : Long.valueOf(strShippingStartTime);
280                                                                    var strShippingEndTime = form.getShippingEndTime();
281                                                                    var shippingEndTime = strShippingEndTime == null ? null : Long.valueOf(strShippingEndTime);
282                                                                    var strSalesOrderStartTime = form.getSalesOrderStartTime();
283                                                                    var salesOrderStartTime = strSalesOrderStartTime == null ? session.getStartTime() : Long.valueOf(strSalesOrderStartTime);
284                                                                    var strSalesOrderEndTime = form.getSalesOrderEndTime();
285                                                                    var salesOrderEndTime = strSalesOrderEndTime == null ? null : Long.valueOf(strSalesOrderEndTime);
286                                                                    var strPurchaseOrderStartTime = form.getPurchaseOrderStartTime();
287                                                                    var purchaseOrderStartTime = isKitOrStyle ? null : strPurchaseOrderStartTime == null ? session.getStartTime() : Long.valueOf(strPurchaseOrderStartTime);
288                                                                    var strPurchaseOrderEndTime = form.getPurchaseOrderEndTime();
289                                                                    var purchaseOrderEndTime = isKitOrStyle ? null : strPurchaseOrderEndTime == null ? null : Long.valueOf(strPurchaseOrderEndTime);
290                                                                    var allowClubDiscounts = Boolean.valueOf(form.getAllowClubDiscounts());
291                                                                    var allowCouponDiscounts = Boolean.valueOf(form.getAllowCouponDiscounts());
292                                                                    var allowAssociatePayments = Boolean.valueOf(form.getAllowAssociatePayments());
293
294                                                                    // TODO: SerialNumberSequenceName is currently ignored.
295                                                                    item = itemLogic.createItem(this, itemName, itemType, itemUseType, itemCategory,
296                                                                            itemAccountingCategory, itemPurchasingCategory, partyCompany.getParty(),
297                                                                            itemDeliveryType, itemInventoryType, inventorySerialized, null, shippingChargeExempt,
298                                                                            shippingStartTime, shippingEndTime, salesOrderStartTime, salesOrderEndTime,
299                                                                            purchaseOrderStartTime, purchaseOrderEndTime, allowClubDiscounts, allowCouponDiscounts,
300                                                                            allowAssociatePayments, unitOfMeasureKind, itemPriceType, cancellationPolicy,
301                                                                            returnPolicy, null, createdBy);
302
303                                                                    if(!hasExecutionErrors()) {
304                                                                        var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(item.getPrimaryKey());
305
306                                                                        workflowControl.addEntityToWorkflow(itemStatus, entityInstance, null, null, createdBy);
307                                                                    }
308                                                                }
309                                                            } else {
310                                                                if(isKitOrStyle) {
311                                                                    if(inventorySerialized != null) {
312                                                                        addExecutionError(ExecutionErrors.NotPermittedInventorySerialized.name());
313                                                                    }
314                                                                } else {
315                                                                    if(inventorySerialized == null) {
316                                                                        addExecutionError(ExecutionErrors.MissingInventorySerialized.name());
317                                                                    }
318                                                                }
319                                                            }
320                                                        } else {
321                                                            addExecutionError(ExecutionErrors.UnknownReturnPolicyName.name(), returnPolicyName);
322                                                        }
323                                                    } else {
324                                                        addExecutionError(ExecutionErrors.UnknownCancellationPolicyName.name(), cancellationPolicyName);
325                                                    }
326                                                } else {
327                                                    addExecutionError(ExecutionErrors.UnknownItemPriceTypeName.name(), itemPriceTypeName);
328                                                }
329                                            } else {
330                                                addExecutionError(ExecutionErrors.UnknownUnitOfMeasureKindName.name(), unitOfMeasureKindName);
331                                            }
332                                        }
333                                    }
334                                } else {
335                                    addExecutionError(ExecutionErrors.UnknownCompanyName.name(), companyName);
336                                }
337                            }
338                        }
339                    } else {
340                        addExecutionError(ExecutionErrors.UnknownItemCategoryName.name(), itemCategoryName);
341                    }
342                } else {
343                    addExecutionError(ExecutionErrors.UnknownItemUseTypeName.name(), itemUseTypeName);
344                }
345            } else {
346                addExecutionError(ExecutionErrors.UnknownItemTypeName.name(), itemTypeName);
347            }
348        } else {
349            addExecutionError(ExecutionErrors.DuplicateItemName.name(), itemName);
350        }
351        
352        if(item != null) {
353            result.setItemName(item.getLastDetail().getItemName());
354            result.setEntityRef(item.getPrimaryKey().getEntityRef());
355        }
356        
357        return result;
358    }
359    
360}