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