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