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