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