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 java.util.List;
058import org.apache.commons.codec.language.Soundex;
059import javax.enterprise.context.Dependent;
060import javax.inject.Inject;
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    @Inject
105    AccountingControl accountingControl;
106
107    @Inject
108    CancellationPolicyControl cancellationPolicyControl;
109
110    @Inject
111    EntityInstanceControl entityInstanceControl;
112
113    @Inject
114    FreeOnBoardControl freeOnBoardControl;
115
116    @Inject
117    ItemControl itemControl;
118
119    @Inject
120    PartyControl partyControl;
121
122    @Inject
123    PartyFreeOnBoardControl partyFreeOnBoardControl;
124
125    @Inject
126    ReturnPolicyControl returnPolicyControl;
127
128    @Inject
129    TermControl termControl;
130
131    @Inject
132    VendorControl vendorControl;
133
134    @Inject
135    WorkflowControl workflowControl;
136
137    @Inject
138    ContactEmailAddressLogic contactEmailAddressLogic;
139
140    @Inject
141    ContactListLogic contactListLogic;
142
143    @Inject
144    VendorLogic vendorLogic;
145
146    
147    /** Creates a new instance of CreateVendorCommand */
148    public CreateVendorCommand() {
149        super(COMMAND_SECURITY_DEFINITION, FORM_FIELD_DEFINITIONS, false);
150    }
151    
152    @Override
153    protected BaseResult execute() {
154        var result = PartyResultFactory.getCreateVendorResult();
155        var vendorName = form.getVendorName();
156        var vendor = vendorName == null ? null : vendorControl.getVendorByName(vendorName);
157
158        if(vendor == null) {
159            var vendorTypeName = form.getVendorTypeName();
160            var vendorType = vendorTypeName == null ? vendorControl.getDefaultVendorType() : vendorControl.getVendorTypeByName(vendorTypeName);
161
162            if(vendorType != null) {
163                var cancellationPolicyName = form.getCancellationPolicyName();
164                CancellationPolicy cancellationPolicy = null;
165
166                if(cancellationPolicyName != null) {
167                    var returnKind = cancellationPolicyControl.getCancellationKindByName(CancellationKinds.VENDOR_CANCELLATION.name());
168
169                    cancellationPolicy = cancellationPolicyControl.getCancellationPolicyByName(returnKind, cancellationPolicyName);
170                }
171
172                if(cancellationPolicyName == null || cancellationPolicy != null) {
173                    var returnPolicyName = form.getReturnPolicyName();
174                    ReturnPolicy returnPolicy = null;
175
176                    if(returnPolicyName != null) {
177                        var returnKind = returnPolicyControl.getReturnKindByName(ReturnKinds.VENDOR_RETURN.name());
178
179                        returnPolicy = returnPolicyControl.getReturnPolicyByName(returnKind, returnPolicyName);
180                    }
181
182                    if(returnPolicyName == null || returnPolicy != null) {
183                        var apGlAccountName = form.getApGlAccountName();
184                        var apGlAccount = apGlAccountName == null ? null : accountingControl.getGlAccountByName(apGlAccountName);
185
186                        if(apGlAccountName == null || apGlAccount != null) {
187                            var glAccountCategoryName = apGlAccount == null ? null
188                                    : apGlAccount.getLastDetail().getGlAccountCategory().getLastDetail().getGlAccountCategoryName();
189
190                            if(glAccountCategoryName == null || glAccountCategoryName.equals(AccountingConstants.GlAccountCategory_ACCOUNTS_PAYABLE)) {
191                                var defaultItemAliasTypeName = form.getDefaultItemAliasTypeName();
192                                var defaultItemAliasType = itemControl.getItemAliasTypeByName(defaultItemAliasTypeName);
193
194                                if(defaultItemAliasTypeName == null || defaultItemAliasType != null) {
195                                    if(defaultItemAliasType == null || !defaultItemAliasType.getLastDetail().getAllowMultiple()) {
196                                        var preferredLanguageIsoName = form.getPreferredLanguageIsoName();
197                                        var preferredLanguage = preferredLanguageIsoName == null ? null : partyControl.getLanguageByIsoName(preferredLanguageIsoName);
198
199                                        if(preferredLanguageIsoName == null || (preferredLanguage != null)) {
200                                            var preferredJavaTimeZoneName = form.getPreferredJavaTimeZoneName();
201                                            var preferredTimeZone = preferredJavaTimeZoneName == null ? null : partyControl.getTimeZoneByJavaName(preferredJavaTimeZoneName);
202
203                                            if(preferredJavaTimeZoneName == null || (preferredTimeZone != null)) {
204                                                var preferredDateTimeFormatName = form.getPreferredDateTimeFormatName();
205                                                var preferredDateTimeFormat = preferredDateTimeFormatName == null ? null : partyControl.getDateTimeFormatByName(preferredDateTimeFormatName);
206
207                                                if(preferredDateTimeFormatName == null || (preferredDateTimeFormat != null)) {
208                                                    var preferredCurrencyIsoName = form.getPreferredCurrencyIsoName();
209                                                    Currency preferredCurrency;
210
211                                                    if(preferredCurrencyIsoName == null) {
212                                                        preferredCurrency = null;
213                                                    } else {
214                                                        preferredCurrency = accountingControl.getCurrencyByIsoName(preferredCurrencyIsoName);
215                                                    }
216
217                                                    if(preferredCurrencyIsoName == null || (preferredCurrency != null)) {
218                                                        var vendorTypeDetail = vendorType.getLastDetail();
219                                                        var soundex = new Soundex();
220                                                        var partyType = partyControl.getPartyTypeByName(PartyTypes.VENDOR.name());
221                                                        BasePK createdBy = getPartyPK();
222                                                        var personalTitleId = form.getPersonalTitleId();
223                                                        var personalTitle = personalTitleId == null ? null : partyControl.convertPersonalTitleIdToEntity(personalTitleId, EntityPermission.READ_ONLY);
224                                                        var firstName = form.getFirstName();
225                                                        var middleName = form.getMiddleName();
226                                                        var lastName = form.getLastName();
227                                                        var nameSuffixId = form.getNameSuffixId();
228                                                        var nameSuffix = nameSuffixId == null ? null : partyControl.convertNameSuffixIdToEntity(nameSuffixId, EntityPermission.READ_ONLY);
229                                                        var name = form.getName();
230                                                        var emailAddress = form.getEmailAddress();
231                                                        var allowSolicitation = Boolean.valueOf(form.getAllowSolicitation());
232                                                        var strMinimumPurchaseOrderLines = form.getMinimumPurchaseOrderLines();
233                                                        var minimumPurchaseOrderLines = strMinimumPurchaseOrderLines == null ? null : Integer.valueOf(strMinimumPurchaseOrderLines);
234                                                        var strMaximumPurchaseOrderLines = form.getMaximumPurchaseOrderLines();
235                                                        var maximumPurchaseOrderLines = strMaximumPurchaseOrderLines == null ? null : Integer.valueOf(strMaximumPurchaseOrderLines);
236                                                        var strMinimumPurchaseOrderAmount = form.getMinimumPurchaseOrderAmount();
237                                                        var minimumPurchaseOrderAmount = strMinimumPurchaseOrderAmount == null ? null : Long.valueOf(strMinimumPurchaseOrderAmount);
238                                                        var strMaximumPurchaseOrderAmount = form.getMaximumPurchaseOrderAmount();
239                                                        var maximumPurchaseOrderAmount = strMaximumPurchaseOrderAmount == null ? null : Long.valueOf(strMaximumPurchaseOrderAmount);
240                                                        var useItemPurchasingCategories = Boolean.valueOf(form.getUseItemPurchasingCategories());
241
242                                                        String firstNameSdx;
243                                                        try {
244                                                            firstNameSdx = firstName == null ? null : soundex.encode(firstName);
245                                                        } catch(IllegalArgumentException iae) {
246                                                            firstNameSdx = null;
247                                                        }
248
249                                                        String middleNameSdx;
250                                                        try {
251                                                            middleNameSdx = middleName == null ? null : soundex.encode(middleName);
252                                                        } catch(IllegalArgumentException iae) {
253                                                            middleNameSdx = null;
254                                                        }
255
256                                                        String lastNameSdx;
257                                                        try {
258                                                            lastNameSdx = lastName == null ? null : soundex.encode(lastName);
259                                                        } catch(IllegalArgumentException iae) {
260                                                            lastNameSdx = null;
261                                                        }
262
263                                                        var party = partyControl.createParty(null, partyType, preferredLanguage, preferredCurrency,
264                                                                preferredTimeZone, preferredDateTimeFormat, createdBy);
265
266                                                        if(createdBy == null) {
267                                                            createdBy = party.getPrimaryKey();
268                                                        }
269
270                                                        if(personalTitle != null || firstName != null || middleName != null || lastName != null || nameSuffix != null) {
271                                                            partyControl.createPerson(party, personalTitle, firstName, firstNameSdx, middleName, middleNameSdx,
272                                                                    lastName, lastNameSdx, nameSuffix, createdBy);
273                                                        }
274
275                                                        if(name != null) {
276                                                            partyControl.createPartyGroup(party, name, createdBy);
277                                                        }
278
279                                                        vendor = vendorLogic.createVendor(this, party, vendorName, vendorType, minimumPurchaseOrderLines,
280                                                                maximumPurchaseOrderLines, minimumPurchaseOrderAmount, maximumPurchaseOrderAmount,
281                                                                useItemPurchasingCategories, defaultItemAliasType, cancellationPolicy, returnPolicy, apGlAccount,
282                                                                vendorTypeDetail.getDefaultHoldUntilComplete(), vendorTypeDetail.getDefaultAllowBackorders(),
283                                                                vendorTypeDetail.getDefaultAllowSubstitutions(), vendorTypeDetail.getDefaultAllowCombiningShipments(),
284                                                                vendorTypeDetail.getDefaultRequireReference(), vendorTypeDetail.getDefaultAllowReferenceDuplicates(),
285                                                                vendorTypeDetail.getDefaultReferenceValidationPattern(), null, null, createdBy);
286
287                                                        if(emailAddress != null) {
288                                                            contactEmailAddressLogic.createContactEmailAddress(party,
289                                                                    emailAddress, allowSolicitation, null,
290                                                                    ContactMechanismPurposes.PRIMARY_EMAIL.name(), createdBy);
291                                                        }
292
293                                                        termControl.createPartyTerm(party, termControl.getDefaultTerm(), null, createdBy);
294
295                                                        partyFreeOnBoardControl.createPartyFreeOnBoard(party, freeOnBoardControl.getDefaultFreeOnBoard(), createdBy);
296
297                                                        contactListLogic.setupInitialContactLists(this, party, createdBy);
298
299                                                        var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(party.getPrimaryKey());
300                                                        workflowControl.addEntityToWorkflowUsingNames(null, VendorStatusConstants.Workflow_VENDOR_STATUS,
301                                                                VendorStatusConstants.WorkflowEntrance_NEW_ACTIVE, entityInstance, null, null, createdBy);
302                                                    } else {
303                                                        addExecutionError(ExecutionErrors.UnknownCurrencyIsoName.name(), preferredCurrencyIsoName);
304                                                    }
305                                                } else {
306                                                    addExecutionError(ExecutionErrors.UnknownDateTimeFormatName.name(), preferredDateTimeFormatName);
307                                                }
308                                            } else {
309                                                addExecutionError(ExecutionErrors.UnknownJavaTimeZoneName.name(), preferredJavaTimeZoneName);
310                                            }
311                                        } else {
312                                            addExecutionError(ExecutionErrors.UnknownLanguageIsoName.name(), preferredLanguageIsoName);
313                                        }
314                                    } else {
315                                        addExecutionError(ExecutionErrors.InvalidItemAliasType.name(), defaultItemAliasTypeName);
316                                    }
317                                } else {
318                                    addExecutionError(ExecutionErrors.UnknownDefaultItemAliasTypeName.name(), defaultItemAliasTypeName);
319                                }
320                            } else {
321                                addExecutionError(ExecutionErrors.InvalidGlAccountCategory.name(), glAccountCategoryName);
322                            }
323                        } else {
324                            addExecutionError(ExecutionErrors.UnknownApGlAccountName.name(), apGlAccountName);
325                        }
326                    } else {
327                        addExecutionError(ExecutionErrors.UnknownReturnPolicyName.name(), returnPolicyName);
328                    }
329                } else {
330                    addExecutionError(ExecutionErrors.UnknownCancellationPolicyName.name(), cancellationPolicyName);
331                }
332            } else {
333                if(vendorTypeName != null) {
334                    addExecutionError(ExecutionErrors.UnknownVendorTypeName.name(), vendorTypeName);
335                } else {
336                    addExecutionError(ExecutionErrors.UnknownDefaultVendorType.name());
337                }
338            }
339        } else {
340            addExecutionError(ExecutionErrors.DuplicateVendorName.name(), vendorName);
341        }
342
343        if(vendor != null) {
344            var party = vendor.getParty();
345
346            result.setEntityRef(party.getPrimaryKey().getEntityRef());
347            result.setVendorName(vendor.getVendorName());
348            result.setPartyName(party.getLastDetail().getPartyName());
349        }
350
351        return result;
352    }
353    
354}