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.offer.server.command; 018 019import com.echothree.control.user.offer.common.edit.OfferEditFactory; 020import com.echothree.control.user.offer.common.edit.OfferItemPriceEdit; 021import com.echothree.control.user.offer.common.form.EditOfferItemPriceForm; 022import com.echothree.control.user.offer.common.result.OfferResultFactory; 023import com.echothree.control.user.offer.common.spec.OfferItemPriceSpec; 024import com.echothree.model.control.accounting.server.control.AccountingControl; 025import com.echothree.model.control.accounting.server.logic.CurrencyLogic; 026import com.echothree.model.control.inventory.server.logic.InventoryConditionLogic; 027import com.echothree.model.control.item.common.ItemPriceTypes; 028import com.echothree.model.control.item.server.logic.ItemLogic; 029import com.echothree.model.control.offer.common.exception.CannotManuallyDeleteOfferItemPriceWhenOfferItemPriceFilterSetException; 030import com.echothree.model.control.offer.server.control.OfferItemControl; 031import com.echothree.model.control.offer.server.logic.OfferItemLogic; 032import com.echothree.model.control.offer.server.logic.OfferLogic; 033import com.echothree.model.control.party.common.PartyTypes; 034import com.echothree.model.control.security.common.SecurityRoleGroups; 035import com.echothree.model.control.security.common.SecurityRoles; 036import com.echothree.model.control.uom.server.logic.UnitOfMeasureTypeLogic; 037import com.echothree.model.data.offer.server.value.OfferItemFixedPriceValue; 038import com.echothree.model.data.offer.server.value.OfferItemVariablePriceValue; 039import com.echothree.model.data.user.common.pk.UserVisitPK; 040import com.echothree.util.common.command.BaseResult; 041import com.echothree.util.common.command.EditMode; 042import com.echothree.util.common.form.BaseForm; 043import com.echothree.util.common.message.ExecutionErrors; 044import com.echothree.util.common.validation.FieldDefinition; 045import com.echothree.util.common.validation.FieldType; 046import com.echothree.util.server.control.BaseEditCommand; 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.Session; 051import com.echothree.util.server.string.AmountUtils; 052import com.echothree.util.server.validation.Validator; 053import java.util.Arrays; 054import java.util.Collections; 055import java.util.List; 056 057public class EditOfferItemPriceCommand 058 extends BaseEditCommand<OfferItemPriceSpec, OfferItemPriceEdit> { 059 060 private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION; 061 private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS; 062 private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS; 063 064 static { 065 COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(Collections.unmodifiableList(Arrays.asList( 066 new PartyTypeDefinition(PartyTypes.UTILITY.name(), null), 067 new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), Collections.unmodifiableList(Arrays.asList( 068 new SecurityRoleDefinition(SecurityRoleGroups.OfferItemPrice.name(), SecurityRoles.Edit.name()) 069 ))) 070 ))); 071 072 SPEC_FIELD_DEFINITIONS = Collections.unmodifiableList(Arrays.asList( 073 new FieldDefinition("OfferName", FieldType.ENTITY_NAME, true, null, 20L), 074 new FieldDefinition("ItemName", FieldType.ENTITY_NAME, true, null, null), 075 new FieldDefinition("InventoryConditionName", FieldType.ENTITY_NAME, true, null, null), 076 new FieldDefinition("UnitOfMeasureTypeName", FieldType.ENTITY_NAME, true, null, null), 077 new FieldDefinition("CurrencyIsoName", FieldType.ENTITY_NAME, true, null, null) 078 )); 079 080 EDIT_FIELD_DEFINITIONS = Collections.unmodifiableList(Arrays.asList( 081 new FieldDefinition("UnitPrice", FieldType.UNSIGNED_PRICE_UNIT, false, null, null), 082 new FieldDefinition("MinimumUnitPrice", FieldType.UNSIGNED_PRICE_UNIT, false, null, null), 083 new FieldDefinition("MaximumUnitPrice", FieldType.UNSIGNED_PRICE_UNIT, false, null, null), 084 new FieldDefinition("UnitPriceIncrement", FieldType.UNSIGNED_PRICE_UNIT, false, null, null) 085 )); 086 } 087 088 /** Creates a new instance of EditOfferItemPriceCommand */ 089 public EditOfferItemPriceCommand(UserVisitPK userVisitPK, EditOfferItemPriceForm form) { 090 super(userVisitPK, form, COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS); 091 } 092 093 @Override 094 protected void setupValidatorForEdit(Validator validator, BaseForm specForm) { 095 var accountingControl = Session.getModelController(AccountingControl.class); 096 String currencyIsoName = spec.getCurrencyIsoName(); 097 098 validator.setCurrency(accountingControl.getCurrencyByIsoName(currencyIsoName)); 099 } 100 101 @Override 102 protected BaseResult execute() { 103 var result = OfferResultFactory.getEditOfferItemPriceResult(); 104 var offerName = spec.getOfferName(); 105 var offer = OfferLogic.getInstance().getOfferByName(this, offerName); 106 107 if(!hasExecutionErrors()) { 108 final var offerDetail = offer.getLastDetail(); 109 110 if(offerDetail.getOfferItemPriceFilter() == null) { 111 var itemName = spec.getItemName(); 112 var inventoryConditionName = spec.getInventoryConditionName(); 113 var unitOfMeasureTypeName = spec.getUnitOfMeasureTypeName(); 114 var currencyIsoName = spec.getCurrencyIsoName(); 115 var item = ItemLogic.getInstance().getItemByName(this, itemName); 116 var inventoryCondition = InventoryConditionLogic.getInstance().getInventoryConditionByName(this, inventoryConditionName); 117 var currency = CurrencyLogic.getInstance().getCurrencyByName(this, currencyIsoName); 118 119 if(!hasExecutionErrors()) { 120 var offerItemControl = Session.getModelController(OfferItemControl.class); 121 var offerItem = offerItemControl.getOfferItem(offer, item); 122 123 if(offerItem != null) { 124 var itemDetail = item.getLastDetail(); 125 var unitOfMeasureKind = item.getLastDetail().getUnitOfMeasureKind(); 126 var unitOfMeasureType = UnitOfMeasureTypeLogic.getInstance().getUnitOfMeasureTypeByName(this, 127 unitOfMeasureKind, unitOfMeasureTypeName); 128 129 if(!hasExecutionErrors()) { 130 var offerItemPrice = offerItemControl.getOfferItemPrice(offerItem, inventoryCondition, 131 unitOfMeasureType, currency); 132 133 if(offerItemPrice != null) { 134 var itemPriceTypeName = itemDetail.getItemPriceType().getItemPriceTypeName(); 135 136 if(editMode.equals(EditMode.LOCK)) { 137 result.setOfferItemPrice(offerItemControl.getOfferItemPriceTransfer(getUserVisit(), offerItemPrice)); 138 139 if(lockEntity(offerItem)) { 140 var edit = OfferEditFactory.getOfferItemPriceEdit(); 141 142 result.setEdit(edit); 143 144 if(itemPriceTypeName.equals(ItemPriceTypes.FIXED.name())) { 145 var offerItemFixedPrice = offerItemControl.getOfferItemFixedPrice(offerItemPrice); 146 147 edit.setUnitPrice(AmountUtils.getInstance().formatPriceUnit(currency, offerItemFixedPrice.getUnitPrice())); 148 } else if(itemPriceTypeName.equals(ItemPriceTypes.VARIABLE.name())) { 149 var offerItemVariablePrice = offerItemControl.getOfferItemVariablePrice(offerItemPrice); 150 151 edit.setMinimumUnitPrice(AmountUtils.getInstance().formatPriceUnit(currency, offerItemVariablePrice.getMinimumUnitPrice())); 152 edit.setMaximumUnitPrice(AmountUtils.getInstance().formatPriceUnit(currency, offerItemVariablePrice.getMaximumUnitPrice())); 153 edit.setUnitPriceIncrement(AmountUtils.getInstance().formatPriceUnit(currency, offerItemVariablePrice.getUnitPriceIncrement())); 154 } else { 155 addExecutionError(ExecutionErrors.UnknownItemPriceType.name(), itemPriceTypeName); 156 } 157 } else { 158 addExecutionError(ExecutionErrors.EntityLockFailed.name()); 159 } 160 161 result.setEntityLock(getEntityLockTransfer(offerItem)); 162 } else if(editMode.equals(EditMode.UPDATE)) { 163 if(itemPriceTypeName.equals(ItemPriceTypes.FIXED.name())) { 164 var strUnitPrice = edit.getUnitPrice(); 165 166 if(strUnitPrice != null) { 167 var unitPrice = Long.valueOf(strUnitPrice); 168 169 if(lockEntityForUpdate(offerItem)) { 170 try { 171 OfferItemFixedPriceValue offerItemFixedPriceValue = offerItemControl.getOfferItemFixedPriceValueForUpdate(offerItemPrice); 172 173 offerItemFixedPriceValue.setUnitPrice(unitPrice); 174 175 OfferItemLogic.getInstance().updateOfferItemFixedPriceFromValue(offerItemFixedPriceValue, getPartyPK()); 176 } finally { 177 unlockEntity(offerItem); 178 } 179 } else { 180 addExecutionError(ExecutionErrors.EntityLockStale.name()); 181 } 182 } else { 183 addExecutionError(ExecutionErrors.MissingUnitPrice.name()); 184 } 185 } else if(itemPriceTypeName.equals(ItemPriceTypes.VARIABLE.name())) { 186 var strMinimumUnitPrice = edit.getMinimumUnitPrice(); 187 Long minimumUnitPrice = null; 188 var strMaximumUnitPrice = edit.getMaximumUnitPrice(); 189 Long maximumUnitPrice = null; 190 var strUnitPriceIncrement = edit.getUnitPriceIncrement(); 191 Long unitPriceIncrement = null; 192 193 if(strMinimumUnitPrice != null) { 194 minimumUnitPrice = Long.valueOf(strMinimumUnitPrice); 195 } else { 196 addExecutionError(ExecutionErrors.MissingMinimumUnitPrice.name()); 197 } 198 199 if(strMaximumUnitPrice != null) { 200 maximumUnitPrice = Long.valueOf(strMaximumUnitPrice); 201 } else { 202 addExecutionError(ExecutionErrors.MissingMaximumUnitPrice.name()); 203 } 204 205 if(strUnitPriceIncrement != null) { 206 unitPriceIncrement = Long.valueOf(strUnitPriceIncrement); 207 } else { 208 addExecutionError(ExecutionErrors.MissingUnitPriceIncrement.name()); 209 } 210 211 if(minimumUnitPrice != null && maximumUnitPrice != null && unitPriceIncrement != null) { 212 if(lockEntityForUpdate(offerItem)) { 213 try { 214 OfferItemVariablePriceValue offerItemVariablePriceValue = offerItemControl.getOfferItemVariablePriceValueForUpdate(offerItemPrice); 215 216 offerItemVariablePriceValue.setMinimumUnitPrice(minimumUnitPrice); 217 offerItemVariablePriceValue.setMaximumUnitPrice(maximumUnitPrice); 218 offerItemVariablePriceValue.setUnitPriceIncrement(unitPriceIncrement); 219 220 OfferItemLogic.getInstance().updateOfferItemVariablePriceFromValue(offerItemVariablePriceValue, getPartyPK()); 221 } finally { 222 unlockEntity(offerItem); 223 } 224 } else { 225 addExecutionError(ExecutionErrors.EntityLockStale.name()); 226 } 227 } 228 } else { 229 addExecutionError(ExecutionErrors.UnknownItemPriceType.name(), itemPriceTypeName); 230 } 231 } 232 } else { 233 addExecutionError(ExecutionErrors.DuplicateOfferItemPrice.name()); 234 } 235 } 236 } else { 237 addExecutionError(ExecutionErrors.UnknownOfferItem.name(), offerName, itemName); 238 } 239 } 240 } else { 241 addExecutionError(ExecutionErrors.CannotManuallyEditOfferItemPriceWhenOfferItemPriceFilterSet.name(), 242 offerDetail.getOfferName()); 243 } 244 } 245 246 return result; 247 } 248 249}