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