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