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.party.server.command;
018
019import com.echothree.control.user.party.common.form.CreateVendorForm;
020import com.echothree.control.user.party.common.result.PartyResultFactory;
021import com.echothree.model.control.accounting.common.AccountingConstants;
022import com.echothree.model.control.accounting.server.control.AccountingControl;
023import com.echothree.model.control.cancellationpolicy.common.CancellationKinds;
024import com.echothree.model.control.cancellationpolicy.server.control.CancellationPolicyControl;
025import com.echothree.model.control.contact.common.ContactMechanismPurposes;
026import com.echothree.model.control.contact.server.logic.ContactEmailAddressLogic;
027import com.echothree.model.control.contactlist.server.logic.ContactListLogic;
028import com.echothree.model.control.core.server.control.EntityInstanceControl;
029import com.echothree.model.control.item.server.control.ItemControl;
030import com.echothree.model.control.party.common.PartyTypes;
031import com.echothree.model.control.party.server.control.PartyControl;
032import com.echothree.model.control.returnpolicy.common.ReturnKinds;
033import com.echothree.model.control.returnpolicy.server.control.ReturnPolicyControl;
034import com.echothree.model.control.security.common.SecurityRoleGroups;
035import com.echothree.model.control.security.common.SecurityRoles;
036import com.echothree.model.control.shipment.server.control.FreeOnBoardControl;
037import com.echothree.model.control.shipment.server.control.PartyFreeOnBoardControl;
038import com.echothree.model.control.term.server.control.TermControl;
039import com.echothree.model.control.vendor.common.workflow.VendorStatusConstants;
040import com.echothree.model.control.vendor.server.control.VendorControl;
041import com.echothree.model.control.vendor.server.logic.VendorLogic;
042import com.echothree.model.control.workflow.server.control.WorkflowControl;
043import com.echothree.model.data.accounting.server.entity.Currency;
044import com.echothree.model.data.cancellationpolicy.server.entity.CancellationPolicy;
045import com.echothree.model.data.returnpolicy.server.entity.ReturnPolicy;
046import com.echothree.model.data.user.common.pk.UserVisitPK;
047import com.echothree.util.common.command.BaseResult;
048import com.echothree.util.common.message.ExecutionErrors;
049import com.echothree.util.common.persistence.BasePK;
050import com.echothree.util.common.validation.FieldDefinition;
051import com.echothree.util.common.validation.FieldType;
052import com.echothree.util.server.control.BaseSimpleCommand;
053import com.echothree.util.server.control.CommandSecurityDefinition;
054import com.echothree.util.server.control.PartyTypeDefinition;
055import com.echothree.util.server.control.SecurityRoleDefinition;
056import com.echothree.util.server.persistence.EntityPermission;
057import com.echothree.util.server.persistence.Session;
058import java.util.List;
059import org.apache.commons.codec.language.Soundex;
060import javax.enterprise.context.Dependent;
061
062@Dependent
063public class CreateVendorCommand
064        extends BaseSimpleCommand<CreateVendorForm> {
065    
066    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
067    private final static List<FieldDefinition> FORM_FIELD_DEFINITIONS;
068    
069    static {
070        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of(
071                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
072                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of(
073                        new SecurityRoleDefinition(SecurityRoleGroups.Vendor.name(), SecurityRoles.Create.name())
074                        ))
075                ));
076        
077        FORM_FIELD_DEFINITIONS = List.of(
078                new FieldDefinition("VendorName", FieldType.ENTITY_NAME, false, null, null),
079                new FieldDefinition("VendorTypeName", FieldType.ENTITY_NAME, false, null, null),
080                new FieldDefinition("CancellationPolicyName", FieldType.ENTITY_NAME, false, null, null),
081                new FieldDefinition("ReturnPolicyName", FieldType.ENTITY_NAME, false, null, null),
082                new FieldDefinition("ApGlAccountName", FieldType.ENTITY_NAME, false, null, null),
083                new FieldDefinition("MinimumPurchaseOrderLines", FieldType.UNSIGNED_INTEGER, false, null, null),
084                new FieldDefinition("MaximumPurchaseOrderLines", FieldType.UNSIGNED_INTEGER, false, null, null),
085                new FieldDefinition("MinimumPurchaseOrderAmount:CurrencyIsoName,PreferredCurrencyIsoName", FieldType.UNSIGNED_COST_LINE, false, null, null),
086                new FieldDefinition("MaximumPurchaseOrderAmount:CurrencyIsoName,PreferredCurrencyIsoName", FieldType.UNSIGNED_COST_LINE, false, null, null),
087                new FieldDefinition("UseItemPurchasingCategories", FieldType.BOOLEAN, true, null, null),
088                new FieldDefinition("DefaultItemAliasTypeName", FieldType.ENTITY_NAME, false, null, null),
089                new FieldDefinition("PersonalTitleId", FieldType.ID, false, null, null),
090                new FieldDefinition("FirstName", FieldType.STRING, false, 1L, 20L),
091                new FieldDefinition("MiddleName", FieldType.STRING, false, 1L, 20L),
092                new FieldDefinition("LastName", FieldType.STRING, false, 1L, 20L),
093                new FieldDefinition("NameSuffixId", FieldType.ID, false, null, null),
094                new FieldDefinition("Name", FieldType.STRING, false, 1L, 60L),
095                new FieldDefinition("PreferredLanguageIsoName", FieldType.ENTITY_NAME, false, null, null),
096                new FieldDefinition("PreferredCurrencyIsoName", FieldType.ENTITY_NAME, false, null, null),
097                new FieldDefinition("PreferredJavaTimeZoneName", FieldType.STRING, false, null, null),
098                new FieldDefinition("PreferredDateTimeFormatName", FieldType.ENTITY_NAME, false, null, null),
099                new FieldDefinition("EmailAddress", FieldType.EMAIL_ADDRESS, false, null, null),
100                new FieldDefinition("AllowSolicitation", FieldType.BOOLEAN, true, null, null)
101                );
102    }
103    
104    /** Creates a new instance of CreateVendorCommand */
105    public CreateVendorCommand() {
106        super(COMMAND_SECURITY_DEFINITION, FORM_FIELD_DEFINITIONS, false);
107    }
108    
109    @Override
110    protected BaseResult execute() {
111        var result = PartyResultFactory.getCreateVendorResult();
112        var vendorControl = Session.getModelController(VendorControl.class);
113        var vendorName = form.getVendorName();
114        var vendor = vendorName == null ? null : vendorControl.getVendorByName(vendorName);
115
116        if(vendor == null) {
117            var vendorTypeName = form.getVendorTypeName();
118            var vendorType = vendorTypeName == null ? vendorControl.getDefaultVendorType() : vendorControl.getVendorTypeByName(vendorTypeName);
119
120            if(vendorType != null) {
121                var cancellationPolicyName = form.getCancellationPolicyName();
122                CancellationPolicy cancellationPolicy = null;
123
124                if(cancellationPolicyName != null) {
125                    var cancellationPolicyControl = Session.getModelController(CancellationPolicyControl.class);
126                    var returnKind = cancellationPolicyControl.getCancellationKindByName(CancellationKinds.VENDOR_CANCELLATION.name());
127
128                    cancellationPolicy = cancellationPolicyControl.getCancellationPolicyByName(returnKind, cancellationPolicyName);
129                }
130
131                if(cancellationPolicyName == null || cancellationPolicy != null) {
132                    var returnPolicyName = form.getReturnPolicyName();
133                    ReturnPolicy returnPolicy = null;
134
135                    if(returnPolicyName != null) {
136                        var returnPolicyControl = Session.getModelController(ReturnPolicyControl.class);
137                        var returnKind = returnPolicyControl.getReturnKindByName(ReturnKinds.VENDOR_RETURN.name());
138
139                        returnPolicy = returnPolicyControl.getReturnPolicyByName(returnKind, returnPolicyName);
140                    }
141
142                    if(returnPolicyName == null || returnPolicy != null) {
143                        var accountingControl = Session.getModelController(AccountingControl.class);
144                        var apGlAccountName = form.getApGlAccountName();
145                        var apGlAccount = apGlAccountName == null ? null : accountingControl.getGlAccountByName(apGlAccountName);
146
147                        if(apGlAccountName == null || apGlAccount != null) {
148                            var glAccountCategoryName = apGlAccount == null ? null
149                                    : apGlAccount.getLastDetail().getGlAccountCategory().getLastDetail().getGlAccountCategoryName();
150
151                            if(glAccountCategoryName == null || glAccountCategoryName.equals(AccountingConstants.GlAccountCategory_ACCOUNTS_PAYABLE)) {
152                                var itemControl = Session.getModelController(ItemControl.class);
153                                var defaultItemAliasTypeName = form.getDefaultItemAliasTypeName();
154                                var defaultItemAliasType = itemControl.getItemAliasTypeByName(defaultItemAliasTypeName);
155
156                                if(defaultItemAliasTypeName == null || defaultItemAliasType != null) {
157                                    if(defaultItemAliasType == null || !defaultItemAliasType.getLastDetail().getAllowMultiple()) {
158                                        var partyControl = Session.getModelController(PartyControl.class);
159                                        var preferredLanguageIsoName = form.getPreferredLanguageIsoName();
160                                        var preferredLanguage = preferredLanguageIsoName == null ? null : partyControl.getLanguageByIsoName(preferredLanguageIsoName);
161
162                                        if(preferredLanguageIsoName == null || (preferredLanguage != null)) {
163                                            var preferredJavaTimeZoneName = form.getPreferredJavaTimeZoneName();
164                                            var preferredTimeZone = preferredJavaTimeZoneName == null ? null : partyControl.getTimeZoneByJavaName(preferredJavaTimeZoneName);
165
166                                            if(preferredJavaTimeZoneName == null || (preferredTimeZone != null)) {
167                                                var preferredDateTimeFormatName = form.getPreferredDateTimeFormatName();
168                                                var preferredDateTimeFormat = preferredDateTimeFormatName == null ? null : partyControl.getDateTimeFormatByName(preferredDateTimeFormatName);
169
170                                                if(preferredDateTimeFormatName == null || (preferredDateTimeFormat != null)) {
171                                                    var preferredCurrencyIsoName = form.getPreferredCurrencyIsoName();
172                                                    Currency preferredCurrency;
173
174                                                    if(preferredCurrencyIsoName == null) {
175                                                        preferredCurrency = null;
176                                                    } else {
177                                                        preferredCurrency = accountingControl.getCurrencyByIsoName(preferredCurrencyIsoName);
178                                                    }
179
180                                                    if(preferredCurrencyIsoName == null || (preferredCurrency != null)) {
181                                                        var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
182                                                        var freeOnBoardControl = Session.getModelController(FreeOnBoardControl.class);
183                                                        var partyFreeOnBoardControl = Session.getModelController(PartyFreeOnBoardControl.class);
184                                                        var termControl = Session.getModelController(TermControl.class);
185                                                        var workflowControl = Session.getModelController(WorkflowControl.class);
186                                                        var vendorTypeDetail = vendorType.getLastDetail();
187                                                        var soundex = new Soundex();
188                                                        var partyType = partyControl.getPartyTypeByName(PartyTypes.VENDOR.name());
189                                                        BasePK createdBy = getPartyPK();
190                                                        var personalTitleId = form.getPersonalTitleId();
191                                                        var personalTitle = personalTitleId == null ? null : partyControl.convertPersonalTitleIdToEntity(personalTitleId, EntityPermission.READ_ONLY);
192                                                        var firstName = form.getFirstName();
193                                                        var middleName = form.getMiddleName();
194                                                        var lastName = form.getLastName();
195                                                        var nameSuffixId = form.getNameSuffixId();
196                                                        var nameSuffix = nameSuffixId == null ? null : partyControl.convertNameSuffixIdToEntity(nameSuffixId, EntityPermission.READ_ONLY);
197                                                        var name = form.getName();
198                                                        var emailAddress = form.getEmailAddress();
199                                                        var allowSolicitation = Boolean.valueOf(form.getAllowSolicitation());
200                                                        var strMinimumPurchaseOrderLines = form.getMinimumPurchaseOrderLines();
201                                                        var minimumPurchaseOrderLines = strMinimumPurchaseOrderLines == null ? null : Integer.valueOf(strMinimumPurchaseOrderLines);
202                                                        var strMaximumPurchaseOrderLines = form.getMaximumPurchaseOrderLines();
203                                                        var maximumPurchaseOrderLines = strMaximumPurchaseOrderLines == null ? null : Integer.valueOf(strMaximumPurchaseOrderLines);
204                                                        var strMinimumPurchaseOrderAmount = form.getMinimumPurchaseOrderAmount();
205                                                        var minimumPurchaseOrderAmount = strMinimumPurchaseOrderAmount == null ? null : Long.valueOf(strMinimumPurchaseOrderAmount);
206                                                        var strMaximumPurchaseOrderAmount = form.getMaximumPurchaseOrderAmount();
207                                                        var maximumPurchaseOrderAmount = strMaximumPurchaseOrderAmount == null ? null : Long.valueOf(strMaximumPurchaseOrderAmount);
208                                                        var useItemPurchasingCategories = Boolean.valueOf(form.getUseItemPurchasingCategories());
209
210                                                        String firstNameSdx;
211                                                        try {
212                                                            firstNameSdx = firstName == null ? null : soundex.encode(firstName);
213                                                        } catch(IllegalArgumentException iae) {
214                                                            firstNameSdx = null;
215                                                        }
216
217                                                        String middleNameSdx;
218                                                        try {
219                                                            middleNameSdx = middleName == null ? null : soundex.encode(middleName);
220                                                        } catch(IllegalArgumentException iae) {
221                                                            middleNameSdx = null;
222                                                        }
223
224                                                        String lastNameSdx;
225                                                        try {
226                                                            lastNameSdx = lastName == null ? null : soundex.encode(lastName);
227                                                        } catch(IllegalArgumentException iae) {
228                                                            lastNameSdx = null;
229                                                        }
230
231                                                        var party = partyControl.createParty(null, partyType, preferredLanguage, preferredCurrency,
232                                                                preferredTimeZone, preferredDateTimeFormat, createdBy);
233
234                                                        if(createdBy == null) {
235                                                            createdBy = party.getPrimaryKey();
236                                                        }
237
238                                                        if(personalTitle != null || firstName != null || middleName != null || lastName != null || nameSuffix != null) {
239                                                            partyControl.createPerson(party, personalTitle, firstName, firstNameSdx, middleName, middleNameSdx,
240                                                                    lastName, lastNameSdx, nameSuffix, createdBy);
241                                                        }
242
243                                                        if(name != null) {
244                                                            partyControl.createPartyGroup(party, name, createdBy);
245                                                        }
246
247                                                        vendor = VendorLogic.getInstance().createVendor(this, party, vendorName, vendorType, minimumPurchaseOrderLines,
248                                                                maximumPurchaseOrderLines, minimumPurchaseOrderAmount, maximumPurchaseOrderAmount,
249                                                                useItemPurchasingCategories, defaultItemAliasType, cancellationPolicy, returnPolicy, apGlAccount,
250                                                                vendorTypeDetail.getDefaultHoldUntilComplete(), vendorTypeDetail.getDefaultAllowBackorders(),
251                                                                vendorTypeDetail.getDefaultAllowSubstitutions(), vendorTypeDetail.getDefaultAllowCombiningShipments(),
252                                                                vendorTypeDetail.getDefaultRequireReference(), vendorTypeDetail.getDefaultAllowReferenceDuplicates(),
253                                                                vendorTypeDetail.getDefaultReferenceValidationPattern(), null, null, createdBy);
254
255                                                        if(emailAddress != null) {
256                                                            ContactEmailAddressLogic.getInstance().createContactEmailAddress(party,
257                                                                    emailAddress, allowSolicitation, null,
258                                                                    ContactMechanismPurposes.PRIMARY_EMAIL.name(), createdBy);
259                                                        }
260
261                                                        termControl.createPartyTerm(party, termControl.getDefaultTerm(), null, createdBy);
262
263                                                        partyFreeOnBoardControl.createPartyFreeOnBoard(party, freeOnBoardControl.getDefaultFreeOnBoard(), createdBy);
264
265                                                        ContactListLogic.getInstance().setupInitialContactLists(this, party, createdBy);
266
267                                                        var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(party.getPrimaryKey());
268                                                        workflowControl.addEntityToWorkflowUsingNames(null, VendorStatusConstants.Workflow_VENDOR_STATUS,
269                                                                VendorStatusConstants.WorkflowEntrance_NEW_ACTIVE, entityInstance, null, null, createdBy);
270                                                    } else {
271                                                        addExecutionError(ExecutionErrors.UnknownCurrencyIsoName.name(), preferredCurrencyIsoName);
272                                                    }
273                                                } else {
274                                                    addExecutionError(ExecutionErrors.UnknownDateTimeFormatName.name(), preferredDateTimeFormatName);
275                                                }
276                                            } else {
277                                                addExecutionError(ExecutionErrors.UnknownJavaTimeZoneName.name(), preferredJavaTimeZoneName);
278                                            }
279                                        } else {
280                                            addExecutionError(ExecutionErrors.UnknownLanguageIsoName.name(), preferredLanguageIsoName);
281                                        }
282                                    } else {
283                                        addExecutionError(ExecutionErrors.InvalidItemAliasType.name(), defaultItemAliasTypeName);
284                                    }
285                                } else {
286                                    addExecutionError(ExecutionErrors.UnknownDefaultItemAliasTypeName.name(), defaultItemAliasTypeName);
287                                }
288                            } else {
289                                addExecutionError(ExecutionErrors.InvalidGlAccountCategory.name(), glAccountCategoryName);
290                            }
291                        } else {
292                            addExecutionError(ExecutionErrors.UnknownApGlAccountName.name(), apGlAccountName);
293                        }
294                    } else {
295                        addExecutionError(ExecutionErrors.UnknownReturnPolicyName.name(), returnPolicyName);
296                    }
297                } else {
298                    addExecutionError(ExecutionErrors.UnknownCancellationPolicyName.name(), cancellationPolicyName);
299                }
300            } else {
301                if(vendorTypeName != null) {
302                    addExecutionError(ExecutionErrors.UnknownVendorTypeName.name(), vendorTypeName);
303                } else {
304                    addExecutionError(ExecutionErrors.UnknownDefaultVendorType.name());
305                }
306            }
307        } else {
308            addExecutionError(ExecutionErrors.DuplicateVendorName.name(), vendorName);
309        }
310
311        if(vendor != null) {
312            var party = vendor.getParty();
313
314            result.setEntityRef(party.getPrimaryKey().getEntityRef());
315            result.setVendorName(vendor.getVendorName());
316            result.setPartyName(party.getLastDetail().getPartyName());
317        }
318
319        return result;
320    }
321    
322}