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.customer.server.command; 018 019import com.echothree.control.user.customer.common.edit.CustomerEdit; 020import com.echothree.control.user.customer.common.edit.CustomerEditFactory; 021import com.echothree.control.user.customer.common.form.EditCustomerForm; 022import com.echothree.control.user.customer.common.result.CustomerResultFactory; 023import com.echothree.control.user.customer.common.result.EditCustomerResult; 024import com.echothree.control.user.customer.common.spec.CustomerSpec; 025import com.echothree.model.control.accounting.common.AccountingConstants; 026import com.echothree.model.control.accounting.server.control.AccountingControl; 027import com.echothree.model.control.cancellationpolicy.common.CancellationKinds; 028import com.echothree.model.control.cancellationpolicy.server.control.CancellationPolicyControl; 029import com.echothree.model.control.customer.server.control.CustomerControl; 030import com.echothree.model.control.party.server.control.PartyControl; 031import com.echothree.model.control.returnpolicy.common.ReturnKinds; 032import com.echothree.model.control.returnpolicy.server.control.ReturnPolicyControl; 033import com.echothree.model.data.accounting.server.entity.Currency; 034import com.echothree.model.data.accounting.server.entity.GlAccount; 035import com.echothree.model.data.cancellationpolicy.server.entity.CancellationPolicy; 036import com.echothree.model.data.customer.server.entity.Customer; 037import com.echothree.model.data.customer.server.entity.CustomerType; 038import com.echothree.model.data.party.server.entity.DateTimeFormat; 039import com.echothree.model.data.party.server.entity.Language; 040import com.echothree.model.data.party.server.entity.Party; 041import com.echothree.model.data.party.server.entity.TimeZone; 042import com.echothree.model.data.returnpolicy.server.entity.ReturnPolicy; 043import com.echothree.model.data.user.common.pk.UserVisitPK; 044import com.echothree.util.common.command.EditMode; 045import com.echothree.util.common.message.ExecutionErrors; 046import com.echothree.util.common.validation.FieldDefinition; 047import com.echothree.util.common.validation.FieldType; 048import com.echothree.util.server.control.BaseAbstractEditCommand; 049import com.echothree.util.server.persistence.EntityPermission; 050import com.echothree.util.server.persistence.Session; 051import java.util.List; 052import org.apache.commons.codec.language.Soundex; 053import javax.enterprise.context.Dependent; 054 055@Dependent 056public class EditCustomerCommand 057 extends BaseAbstractEditCommand<CustomerSpec, CustomerEdit, EditCustomerResult, Party, Party> { 058 059 private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS; 060 private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS; 061 062 static { 063 SPEC_FIELD_DEFINITIONS = List.of( 064 new FieldDefinition("CustomerName", FieldType.ENTITY_NAME, true, null, null) 065 ); 066 067 EDIT_FIELD_DEFINITIONS = List.of( 068 new FieldDefinition("CustomerTypeName", FieldType.ENTITY_NAME, true, null, null), 069 new FieldDefinition("CancellationPolicyName", FieldType.ENTITY_NAME, false, null, null), 070 new FieldDefinition("ReturnPolicyName", FieldType.ENTITY_NAME, false, null, null), 071 new FieldDefinition("ArGlAccountName", FieldType.ENTITY_NAME, false, null, null), 072 new FieldDefinition("PersonalTitleId", FieldType.ID, false, null, null), 073 new FieldDefinition("FirstName", FieldType.STRING, false, 1L, 20L), 074 new FieldDefinition("MiddleName", FieldType.STRING, false, 1L, 20L), 075 new FieldDefinition("LastName", FieldType.STRING, false, 1L, 20L), 076 new FieldDefinition("NameSuffixId", FieldType.ID, false, null, null), 077 new FieldDefinition("Name", FieldType.STRING, false, 1L, 60L), 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("HoldUntilComplete", FieldType.BOOLEAN, true, null, null), 083 new FieldDefinition("AllowBackorders", FieldType.BOOLEAN, true, null, null), 084 new FieldDefinition("AllowSubstitutions", FieldType.BOOLEAN, true, null, null), 085 new FieldDefinition("AllowCombiningShipments", FieldType.BOOLEAN, true, null, null), 086 new FieldDefinition("RequireReference", FieldType.BOOLEAN, true, null, null), 087 new FieldDefinition("AllowReferenceDuplicates", FieldType.BOOLEAN, true, null, null), 088 new FieldDefinition("ReferenceValidationPattern", FieldType.REGULAR_EXPRESSION, false, null, null) 089 ); 090 } 091 092 /** Creates a new instance of EditCustomerCommand */ 093 public EditCustomerCommand() { 094 super(null, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS); 095 } 096 097 @Override 098 public EditCustomerResult getResult() { 099 return CustomerResultFactory.getEditCustomerResult(); 100 } 101 102 @Override 103 public CustomerEdit getEdit() { 104 return CustomerEditFactory.getCustomerEdit(); 105 } 106 107 @Override 108 public Party getEntity(EditCustomerResult result) { 109 var customerControl = Session.getModelController(CustomerControl.class); 110 Customer customer; 111 var customerName = spec.getCustomerName(); 112 113 if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) { 114 customer = customerControl.getCustomerByName(customerName); 115 } else { // EditMode.UPDATE 116 customer = customerControl.getCustomerByNameForUpdate(customerName); 117 } 118 119 if(customer != null) { 120 result.setCustomer(customerControl.getCustomerTransfer(getUserVisit(), customer)); 121 } else { 122 addExecutionError(ExecutionErrors.UnknownCustomerName.name(), customerName); 123 } 124 125 return customer.getParty(); 126 } 127 128 @Override 129 public Party getLockEntity(Party party) { 130 return party; 131 } 132 133 @Override 134 public void fillInResult(EditCustomerResult result, Party party) { 135 var customerControl = Session.getModelController(CustomerControl.class); 136 137 result.setCustomer(customerControl.getCustomerTransfer(getUserVisit(), party)); 138 } 139 140 @Override 141 public void doLock(CustomerEdit edit, Party party) { 142 var customerControl = Session.getModelController(CustomerControl.class); 143 var partyControl = Session.getModelController(PartyControl.class); 144 var customer = customerControl.getCustomer(party); 145 var partyDetail = party.getLastDetail(); 146 var partyGroup = partyControl.getPartyGroup(party); 147 var arGlAccount = customer.getArGlAccount(); 148 var cancellationPolicy = customer.getCancellationPolicy(); 149 var returnPolicy = customer.getReturnPolicy(); 150 var preferredLanguage = partyDetail.getPreferredLanguage(); 151 var preferredCurrency = partyDetail.getPreferredCurrency(); 152 var preferredTimeZone = partyDetail.getPreferredTimeZone(); 153 var dateTimeFormat = partyDetail.getPreferredDateTimeFormat(); 154 var person = partyControl.getPerson(party); 155 var personalTitle = person == null ? null : person.getPersonalTitle(); 156 var nameSuffix = person == null ? null : person.getNameSuffix(); 157 158 edit.setCustomerTypeName(customer.getCustomerType().getLastDetail().getCustomerTypeName()); 159 edit.setPersonalTitleId(personalTitle == null ? null : personalTitle.getPrimaryKey().getEntityId().toString()); 160 edit.setFirstName(person == null ? null : person.getFirstName()); 161 edit.setMiddleName(person == null ? null : person.getMiddleName()); 162 edit.setLastName(person == null ? null : person.getLastName()); 163 edit.setNameSuffixId(nameSuffix == null ? null : nameSuffix.getPrimaryKey().getEntityId().toString()); 164 edit.setName(partyGroup == null ? null : partyGroup.getName()); 165 edit.setPreferredLanguageIsoName(preferredLanguage == null ? null : preferredLanguage.getLanguageIsoName()); 166 edit.setPreferredCurrencyIsoName(preferredCurrency == null ? null : preferredCurrency.getCurrencyIsoName()); 167 edit.setPreferredJavaTimeZoneName(preferredTimeZone == null ? null : preferredTimeZone.getLastDetail().getJavaTimeZoneName()); 168 edit.setPreferredDateTimeFormatName(dateTimeFormat == null ? null : dateTimeFormat.getLastDetail().getDateTimeFormatName()); 169 edit.setArGlAccountName(arGlAccount == null ? null : arGlAccount.getLastDetail().getGlAccountName()); 170 edit.setCancellationPolicyName(cancellationPolicy == null ? null : cancellationPolicy.getLastDetail().getCancellationPolicyName()); 171 edit.setReturnPolicyName(returnPolicy == null ? null : returnPolicy.getLastDetail().getReturnPolicyName()); 172 edit.setHoldUntilComplete(customer.getHoldUntilComplete().toString()); 173 edit.setAllowBackorders(customer.getAllowBackorders().toString()); 174 edit.setAllowSubstitutions(customer.getAllowSubstitutions().toString()); 175 edit.setAllowCombiningShipments(customer.getAllowCombiningShipments().toString()); 176 edit.setRequireReference(customer.getRequireReference().toString()); 177 edit.setAllowReferenceDuplicates(customer.getAllowReferenceDuplicates().toString()); 178 edit.setReferenceValidationPattern(customer.getReferenceValidationPattern()); 179 } 180 181 CustomerType customerType; 182 CancellationPolicy cancellationPolicy; 183 ReturnPolicy returnPolicy; 184 GlAccount arGlAccount; 185 Language preferredLanguage; 186 TimeZone preferredTimeZone; 187 DateTimeFormat preferredDateTimeFormat; 188 Currency preferredCurrency; 189 190 @Override 191 public void canUpdate(Party party) { 192 var customerControl = Session.getModelController(CustomerControl.class); 193 var partyControl = Session.getModelController(PartyControl.class); 194 var customerTypeName = edit.getCustomerTypeName(); 195 196 customerType = customerControl.getCustomerTypeByName(customerTypeName); 197 198 if(customerType != null) { 199 var cancellationPolicyName = edit.getCancellationPolicyName(); 200 201 if(cancellationPolicyName != null) { 202 var cancellationPolicyControl = Session.getModelController(CancellationPolicyControl.class); 203 var cancellationKind = cancellationPolicyControl.getCancellationKindByName(CancellationKinds.CUSTOMER_CANCELLATION.name()); 204 205 cancellationPolicy = cancellationPolicyControl.getCancellationPolicyByName(cancellationKind, cancellationPolicyName); 206 } 207 208 if(cancellationPolicyName == null || cancellationPolicy != null) { 209 var returnPolicyName = edit.getReturnPolicyName(); 210 211 if(returnPolicyName != null) { 212 var returnPolicyControl = Session.getModelController(ReturnPolicyControl.class); 213 var returnKind = returnPolicyControl.getReturnKindByName(ReturnKinds.CUSTOMER_RETURN.name()); 214 215 returnPolicy = returnPolicyControl.getReturnPolicyByName(returnKind, returnPolicyName); 216 } 217 218 if(returnPolicyName == null || returnPolicy != null) { 219 var accountingControl = Session.getModelController(AccountingControl.class); 220 var arGlAccountName = edit.getArGlAccountName(); 221 222 arGlAccount = arGlAccountName == null ? null : accountingControl.getGlAccountByName(arGlAccountName); 223 224 if(arGlAccountName == null || arGlAccount != null) { 225 var glAccountCategoryName = arGlAccount == null ? null : arGlAccount.getLastDetail().getGlAccountCategory().getLastDetail().getGlAccountCategoryName(); 226 227 if(glAccountCategoryName == null || glAccountCategoryName.equals(AccountingConstants.GlAccountCategory_ACCOUNTS_RECEIVABLE)) { 228 var preferredLanguageIsoName = edit.getPreferredLanguageIsoName(); 229 230 preferredLanguage = preferredLanguageIsoName == null ? null : partyControl.getLanguageByIsoName(preferredLanguageIsoName); 231 232 if(preferredLanguageIsoName == null || (preferredLanguage != null)) { 233 var preferredJavaTimeZoneName = edit.getPreferredJavaTimeZoneName(); 234 235 preferredTimeZone = preferredJavaTimeZoneName == null ? null : partyControl.getTimeZoneByJavaName(preferredJavaTimeZoneName); 236 237 if(preferredJavaTimeZoneName == null || (preferredTimeZone != null)) { 238 var preferredDateTimeFormatName = edit.getPreferredDateTimeFormatName(); 239 240 preferredDateTimeFormat = preferredDateTimeFormatName == null ? null : partyControl.getDateTimeFormatByName(preferredDateTimeFormatName); 241 242 if(preferredDateTimeFormatName == null || (preferredDateTimeFormat != null)) { 243 var preferredCurrencyIsoName = edit.getPreferredCurrencyIsoName(); 244 245 if(preferredCurrencyIsoName == null) { 246 preferredCurrency = null; 247 } else { 248 preferredCurrency = accountingControl.getCurrencyByIsoName(preferredCurrencyIsoName); 249 } 250 251 if(preferredCurrencyIsoName != null && (preferredCurrency == null)) { 252 addExecutionError(ExecutionErrors.UnknownCurrencyIsoName.name(), preferredCurrencyIsoName); 253 } 254 } else { 255 addExecutionError(ExecutionErrors.UnknownDateTimeFormatName.name(), preferredDateTimeFormatName); 256 } 257 } else { 258 addExecutionError(ExecutionErrors.UnknownJavaTimeZoneName.name(), preferredJavaTimeZoneName); 259 } 260 } else { 261 addExecutionError(ExecutionErrors.UnknownLanguageIsoName.name(), preferredLanguageIsoName); 262 } 263 } else { 264 addExecutionError(ExecutionErrors.InvalidGlAccountCategory.name(), glAccountCategoryName); 265 } 266 } else { 267 addExecutionError(ExecutionErrors.UnknownArGlAccountName.name(), arGlAccountName); 268 } 269 } else { 270 addExecutionError(ExecutionErrors.UnknownReturnPolicyName.name(), returnPolicyName); 271 } 272 } else { 273 addExecutionError(ExecutionErrors.UnknownCancellationPolicyName.name(), cancellationPolicyName); 274 } 275 } else { 276 addExecutionError(ExecutionErrors.UnknownCustomerTypeName.name(), customerTypeName); 277 } 278 } 279 280 @Override 281 public void doUpdate(Party party) { 282 var customerControl = Session.getModelController(CustomerControl.class); 283 var partyControl = Session.getModelController(PartyControl.class); 284 var soundex = new Soundex(); 285 var partyDetailValue = partyControl.getPartyDetailValueForUpdate(party); 286 var customer = customerControl.getCustomerForUpdate(party); 287 var customerValue = customerControl.getCustomerValue(customer); 288 var partyGroup = partyControl.getPartyGroupForUpdate(party); 289 var person = partyControl.getPersonForUpdate(party); 290 var personalTitleId = edit.getPersonalTitleId(); 291 var personalTitle = personalTitleId == null ? null : partyControl.convertPersonalTitleIdToEntity(personalTitleId, EntityPermission.READ_ONLY); 292 var firstName = edit.getFirstName(); 293 var firstNameSdx = soundex.encode(firstName); 294 var middleName = edit.getMiddleName(); 295 var middleNameSdx = middleName == null ? null : soundex.encode(middleName); 296 var lastName = edit.getLastName(); 297 var lastNameSdx = soundex.encode(lastName); 298 var nameSuffixId = edit.getNameSuffixId(); 299 var nameSuffix = nameSuffixId == null ? null : partyControl.convertNameSuffixIdToEntity(nameSuffixId, EntityPermission.READ_ONLY); 300 var name = edit.getName(); 301 var updatedBy = getPartyPK(); 302 303 customerValue.setCustomerTypePK(customerType.getPrimaryKey()); 304 customerValue.setArGlAccountPK(arGlAccount == null ? null : arGlAccount.getPrimaryKey()); 305 customerValue.setCancellationPolicyPK(cancellationPolicy == null ? null : cancellationPolicy.getPrimaryKey()); 306 customerValue.setReturnPolicyPK(returnPolicy == null ? null : returnPolicy.getPrimaryKey()); 307 customerValue.setHoldUntilComplete(Boolean.valueOf(edit.getHoldUntilComplete())); 308 customerValue.setAllowBackorders(Boolean.valueOf(edit.getAllowBackorders())); 309 customerValue.setAllowSubstitutions(Boolean.valueOf(edit.getAllowSubstitutions())); 310 customerValue.setAllowCombiningShipments(Boolean.valueOf(edit.getAllowCombiningShipments())); 311 customerValue.setRequireReference(Boolean.valueOf(edit.getRequireReference())); 312 customerValue.setAllowReferenceDuplicates(Boolean.valueOf(edit.getAllowReferenceDuplicates())); 313 customerValue.setReferenceValidationPattern(edit.getReferenceValidationPattern()); 314 315 partyDetailValue.setPreferredLanguagePK(preferredLanguage == null ? null : preferredLanguage.getPrimaryKey()); 316 partyDetailValue.setPreferredTimeZonePK(preferredTimeZone == null ? null : preferredTimeZone.getPrimaryKey()); 317 partyDetailValue.setPreferredDateTimeFormatPK(preferredDateTimeFormat == null ? null : preferredDateTimeFormat.getPrimaryKey()); 318 partyDetailValue.setPreferredCurrencyPK(preferredCurrency == null ? null : preferredCurrency.getPrimaryKey()); 319 320 if(name != null) { 321 if(partyGroup != null) { 322 var partyGroupValue = partyControl.getPartyGroupValue(partyGroup); 323 324 partyGroupValue.setName(name); 325 partyControl.updatePartyGroupFromValue(partyGroupValue, updatedBy); 326 } else { 327 partyControl.createPartyGroup(party, name, updatedBy); 328 } 329 } else { 330 if(partyGroup != null) { 331 partyControl.deletePartyGroup(partyGroup, updatedBy); 332 } 333 } 334 335 if(personalTitle != null || firstName != null || middleName != null || lastName != null || nameSuffix != null) { 336 if(person != null) { 337 var personValue = partyControl.getPersonValue(person); 338 339 personValue.setPersonalTitlePK(personalTitle == null ? null : personalTitle.getPrimaryKey()); 340 personValue.setFirstName(firstName); 341 personValue.setFirstNameSdx(firstNameSdx); 342 personValue.setMiddleName(middleName); 343 personValue.setMiddleNameSdx(middleNameSdx); 344 personValue.setLastName(lastName); 345 personValue.setLastNameSdx(lastNameSdx); 346 personValue.setNameSuffixPK(nameSuffix == null ? null : nameSuffix.getPrimaryKey()); 347 partyControl.updatePersonFromValue(personValue, updatedBy); 348 } else { 349 partyControl.createPerson(party, personalTitle, firstName, firstNameSdx, middleName, middleNameSdx, 350 lastName, lastNameSdx, nameSuffix, updatedBy); 351 } 352 } else { 353 if(person != null) { 354 partyControl.deletePerson(person, updatedBy); 355 } 356 } 357 358 customerControl.updateCustomerFromValue(customerValue, updatedBy); 359 partyControl.updatePartyFromValue(partyDetailValue, updatedBy); 360 } 361 362}