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.CreateEmployeeForm;
020import com.echothree.control.user.party.common.result.PartyResultFactory;
021import com.echothree.model.control.accounting.server.control.AccountingControl;
022import com.echothree.model.control.contact.common.ContactMechanismPurposes;
023import com.echothree.model.control.contact.server.logic.ContactEmailAddressLogic;
024import com.echothree.model.control.contactlist.server.logic.ContactListLogic;
025import com.echothree.model.control.core.server.control.EntityInstanceControl;
026import com.echothree.model.control.employee.common.workflow.EmployeeAvailabilityConstants;
027import com.echothree.model.control.employee.common.workflow.EmployeeStatusConstants;
028import com.echothree.model.control.employee.server.control.EmployeeControl;
029import com.echothree.model.control.party.common.PartyTypes;
030import com.echothree.model.control.party.server.control.PartyControl;
031import com.echothree.model.control.party.server.logic.PasswordStringPolicyLogic;
032import com.echothree.model.control.security.common.SecurityRoleGroups;
033import com.echothree.model.control.security.common.SecurityRoles;
034import com.echothree.model.control.security.server.control.SecurityControl;
035import com.echothree.model.control.sequence.common.SequenceTypes;
036import com.echothree.model.control.sequence.server.logic.SequenceGeneratorLogic;
037import com.echothree.model.control.user.common.UserConstants;
038import com.echothree.model.control.workflow.server.control.WorkflowControl;
039import com.echothree.model.data.accounting.server.entity.Currency;
040import com.echothree.model.data.employee.server.entity.PartyEmployee;
041import com.echothree.util.common.command.BaseResult;
042import com.echothree.util.common.message.ExecutionErrors;
043import com.echothree.util.common.persistence.BasePK;
044import com.echothree.util.common.validation.FieldDefinition;
045import com.echothree.util.common.validation.FieldType;
046import com.echothree.util.server.control.BaseSimpleCommand;
047import com.echothree.util.server.control.CommandSecurityDefinition;
048import com.echothree.util.server.control.PartyTypeDefinition;
049import com.echothree.util.server.control.SecurityRoleDefinition;
050import com.echothree.util.server.persistence.EntityPermission;
051import com.echothree.util.server.persistence.Session;
052import java.util.List;
053import org.apache.commons.codec.language.Soundex;
054import javax.enterprise.context.Dependent;
055
056@Dependent
057public class CreateEmployeeCommand
058        extends BaseSimpleCommand<CreateEmployeeForm> {
059    
060    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
061    private final static List<FieldDefinition> FORM_FIELD_DEFINITIONS;
062    
063    static {
064        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of(
065                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
066                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of(
067                        new SecurityRoleDefinition(SecurityRoleGroups.Employee.name(), SecurityRoles.Create.name())
068                        ))
069                ));
070        
071        FORM_FIELD_DEFINITIONS = List.of(
072                new FieldDefinition("EmployeeTypeName", FieldType.ENTITY_NAME, false, null, null),
073                new FieldDefinition("PersonalTitleId", FieldType.ID, false, null, null),
074                new FieldDefinition("FirstName", FieldType.STRING, true, 1L, 20L),
075                new FieldDefinition("MiddleName", FieldType.STRING, false, 1L, 20L),
076                new FieldDefinition("LastName", FieldType.STRING, true, 1L, 20L),
077                new FieldDefinition("NameSuffixId", FieldType.ID, false, null, null),
078                new FieldDefinition("PreferredLanguageIsoName", FieldType.ENTITY_NAME, false, null, null),
079                new FieldDefinition("PreferredCurrencyIsoName", FieldType.ENTITY_NAME, false, null, null),
080                new FieldDefinition("PreferredJavaTimeZoneName", FieldType.TIME_ZONE_NAME, false, null, null),
081                new FieldDefinition("PreferredDateTimeFormatName", FieldType.ENTITY_NAME, false, null, null),
082                new FieldDefinition("EmailAddress", FieldType.EMAIL_ADDRESS, true, null, null),
083                new FieldDefinition("AllowSolicitation", FieldType.BOOLEAN, true, null, null),
084                new FieldDefinition("Username", FieldType.STRING, true, 1L, 80L),
085                new FieldDefinition("Password1", FieldType.STRING, true, 1L, 40L),
086                new FieldDefinition("Password2", FieldType.STRING, true, 1L, 40L),
087                new FieldDefinition("PartySecurityRoleTemplateName", FieldType.ENTITY_NAME, true, null, null)
088                );
089    }
090    
091    /** Creates a new instance of CreateEmployeeCommand */
092    public CreateEmployeeCommand() {
093        super(COMMAND_SECURITY_DEFINITION, FORM_FIELD_DEFINITIONS, false);
094    }
095    
096    @Override
097    protected BaseResult execute() {
098        var employeeControl = Session.getModelController(EmployeeControl.class);
099        var userControl = getUserControl();
100        var result = PartyResultFactory.getCreateEmployeeResult();
101        PartyEmployee partyEmployee = null;
102        var username = form.getUsername();
103        var userLogin = userControl.getUserLoginByUsername(username);
104        
105        if(userLogin == null) {
106            var password1 = form.getPassword1();
107            var password2 = form.getPassword2();
108            
109            if(password1.equals(password2)) {
110                var partyControl = Session.getModelController(PartyControl.class);
111                var partyType = partyControl.getPartyTypeByName(PartyTypes.EMPLOYEE.name());
112                var partyTypePasswordStringPolicy = PasswordStringPolicyLogic.getInstance().checkStringPassword(session,
113                        getUserVisit(), this, partyType, null, null, password1);
114                
115                if(!hasExecutionErrors()) {
116                    var employeeTypeName = form.getEmployeeTypeName();
117                    var employeeType = employeeTypeName == null? employeeControl.getDefaultEmployeeType(): employeeControl.getEmployeeTypeByName(employeeTypeName);
118                    
119                    if(employeeType != null) {
120                        var preferredLanguageIsoName = form.getPreferredLanguageIsoName();
121                        var preferredLanguage = preferredLanguageIsoName == null? null: partyControl.getLanguageByIsoName(preferredLanguageIsoName);
122                        
123                        if(preferredLanguageIsoName == null || (preferredLanguage != null)) {
124                            var preferredJavaTimeZoneName = form.getPreferredJavaTimeZoneName();
125                            var preferredTimeZone = preferredJavaTimeZoneName == null? null: partyControl.getTimeZoneByJavaName(preferredJavaTimeZoneName);
126                            
127                            if(preferredJavaTimeZoneName == null || (preferredTimeZone != null)) {
128                                var preferredDateTimeFormatName = form.getPreferredDateTimeFormatName();
129                                var preferredDateTimeFormat = preferredDateTimeFormatName == null? null: partyControl.getDateTimeFormatByName(preferredDateTimeFormatName);
130                                
131                                if(preferredDateTimeFormatName == null || (preferredDateTimeFormat != null)) {
132                                    var preferredCurrencyIsoName = form.getPreferredCurrencyIsoName();
133                                    Currency preferredCurrency;
134                                    
135                                    if(preferredCurrencyIsoName == null)
136                                        preferredCurrency = null;
137                                    else {
138                                        var accountingControl = Session.getModelController(AccountingControl.class);
139                                        preferredCurrency = accountingControl.getCurrencyByIsoName(preferredCurrencyIsoName);
140                                    }
141                                    
142                                    if(preferredCurrencyIsoName == null || (preferredCurrency != null)) {
143                                        var securityControl = Session.getModelController(SecurityControl.class);
144                                        var partySecurityRoleTemplateName = form.getPartySecurityRoleTemplateName();
145                                        var partySecurityRoleTemplate = securityControl.getPartySecurityRoleTemplateByName(partySecurityRoleTemplateName);
146                                        
147                                        if(partySecurityRoleTemplate != null) {
148                                            var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
149                                            var workflowControl = Session.getModelController(WorkflowControl.class);
150                                            var soundex = new Soundex();
151                                            BasePK createdBy = getPartyPK();
152                                            var personalTitleId = form.getPersonalTitleId();
153                                            var personalTitle = personalTitleId == null? null: partyControl.convertPersonalTitleIdToEntity(personalTitleId, EntityPermission.READ_ONLY);
154                                            var firstName = form.getFirstName();
155                                            var firstNameSdx = soundex.encode(firstName);
156                                            var middleName = form.getMiddleName();
157                                            var middleNameSdx = middleName == null? null: soundex.encode(middleName);
158                                            var lastName = form.getLastName();
159                                            var lastNameSdx = soundex.encode(lastName);
160                                            var nameSuffixId = form.getNameSuffixId();
161                                            var nameSuffix = nameSuffixId == null? null: partyControl.convertNameSuffixIdToEntity(nameSuffixId, EntityPermission.READ_ONLY);
162                                            var emailAddress = form.getEmailAddress();
163                                            var allowSolicitation = Boolean.valueOf(form.getAllowSolicitation());
164                                            var partyEmployeeName = SequenceGeneratorLogic.getInstance().getNextSequenceValue(null, SequenceTypes.EMPLOYEE.name());
165
166                                            var party = partyControl.createParty(null, partyType, preferredLanguage, preferredCurrency, preferredTimeZone, preferredDateTimeFormat, createdBy);
167                                            partyControl.createPerson(party, personalTitle, firstName, firstNameSdx, middleName, middleNameSdx, lastName, lastNameSdx, nameSuffix, createdBy);
168                                            partyEmployee = employeeControl.createPartyEmployee(party, partyEmployeeName, employeeType, createdBy);
169                                            userControl.createUserLogin(party, username, createdBy);
170                                            
171                                            ContactEmailAddressLogic.getInstance().createContactEmailAddress(party,
172                                                    emailAddress, allowSolicitation, null,
173                                                    ContactMechanismPurposes.PRIMARY_EMAIL.name(), createdBy);
174
175                                            var userLoginPasswordType = userControl.getUserLoginPasswordTypeByName(UserConstants.UserLoginPasswordType_STRING);
176                                            var userLoginPassword = userControl.createUserLoginPassword(party, userLoginPasswordType, createdBy);
177                                            userControl.createUserLoginPasswordString(userLoginPassword, password1, session.getStartTime(), false, createdBy);
178
179                                            if(partyTypePasswordStringPolicy != null && partyTypePasswordStringPolicy.getLastDetail().getForceChangeAfterCreate()) {
180                                                var userLoginStatus = userControl.getUserLoginStatusForUpdate(party);
181
182                                                userLoginStatus.setForceChange(true);
183                                            }
184
185                                            securityControl.createPartySecurityRoleTemplateUse(party, partySecurityRoleTemplate, createdBy);
186
187                                            var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(party.getPrimaryKey());
188                                            workflowControl.addEntityToWorkflowUsingNames(null, EmployeeStatusConstants.Workflow_EMPLOYEE_STATUS,
189                                                    EmployeeStatusConstants.WorkflowEntrance_NEW_ACTIVE, entityInstance, null, null, createdBy);
190                                            workflowControl.addEntityToWorkflowUsingNames(null, EmployeeAvailabilityConstants.Workflow_EMPLOYEE_AVAILABILITY,
191                                                    EmployeeAvailabilityConstants.WorkflowEntrance_NEW_AVAILABLE, entityInstance, null, null, createdBy);
192                                            
193                                            ContactListLogic.getInstance().setupInitialContactLists(this, party, createdBy);
194                                        } else {
195                                            addExecutionError(ExecutionErrors.UnknownPartySecurityRoleTemplateName.name(), partySecurityRoleTemplateName);
196                                        }
197                                    } else {
198                                        addExecutionError(ExecutionErrors.UnknownCurrencyIsoName.name(), preferredCurrencyIsoName);
199                                    }
200                                } else {
201                                    addExecutionError(ExecutionErrors.UnknownDateTimeFormatName.name(), preferredDateTimeFormatName);
202                                }
203                            } else {
204                                addExecutionError(ExecutionErrors.UnknownJavaTimeZoneName.name(), preferredJavaTimeZoneName);
205                            }
206                        } else {
207                            addExecutionError(ExecutionErrors.UnknownLanguageIsoName.name(), preferredLanguageIsoName);
208                        }
209                    } else {
210                        if(employeeTypeName != null) {
211                            addExecutionError(ExecutionErrors.UnknownEmployeeTypeName.name(), employeeTypeName);
212                        } else {
213                            addExecutionError(ExecutionErrors.UnknownDefaultEmployeeType.name());
214                        }
215                    }
216                }
217            } else {
218                addExecutionError(ExecutionErrors.MismatchedPasswords.name());
219            }
220        } else {
221            addExecutionError(ExecutionErrors.DuplicateUsername.name());
222
223            var party = userLogin.getParty();
224            partyEmployee = employeeControl.getPartyEmployee(party);
225        }
226        
227        if(partyEmployee != null) {
228            var party = partyEmployee.getParty();
229            
230            result.setEntityRef(party.getPrimaryKey().getEntityRef());
231            result.setEmployeeName(partyEmployee.getPartyEmployeeName());
232            result.setPartyName(party.getLastDetail().getPartyName());
233        }
234        
235        return result;
236    }
237    
238}