ProductVO.java
/*
* Copyright 2005-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openwms.wms.inventory.api;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.ameba.http.AbstractBase;
import org.openwms.core.units.api.Measurable;
import org.openwms.core.units.api.Weight;
import org.openwms.wms.location.api.LocationVO;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
/**
* A ProductVO.
*
* @author Heiko Scherrer
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class ProductVO extends AbstractBase<ProductVO> {
public static final String FIELD_PKEY = "pKey";
public static final String FIELD_SKU = "sku";
public static final String FIELD_LABEL = "label";
public static final String FIELD_ACCOUNT_ID = "accountId";
public static final String FIELD_BASE_UNIT = "baseUnit";
public static final String FIELD_OVERBOOKING_ALLOWED = "overbookingAllowed";
public static final String FIELD_DESCRIPTION = "description";
public static final String FIELD_AVAILABILITY_STATE = "availabilityState";
public static final String FIELD_CLASSIFICATION = "classification";
public static final String FIELD_GROUP = "group";
public static final String FIELD_STOCK_ZONE = "stockZone";
public static final String FIELD_UNITS = "units";
public static final String FIELD_DIMENSION = "dimension";
public static final String FIELD_NET_WEIGHT = "netWeight";
public static final String FIELD_PREFERABLE_STORAGE_LOCATION = "preferableStorageLocation";
public static final String FIELD_STACKING_RULES = "stackingRules";
public static final String FIELD_DETAILS = "details";
public static final List<String> FIELD_NAMES =
Stream.of(FIELD_PKEY, FIELD_SKU, FIELD_LABEL, FIELD_ACCOUNT_ID, FIELD_BASE_UNIT, FIELD_OVERBOOKING_ALLOWED, FIELD_DESCRIPTION, FIELD_AVAILABILITY_STATE, FIELD_CLASSIFICATION,
FIELD_GROUP, FIELD_STOCK_ZONE, FIELD_UNITS, FIELD_DIMENSION, FIELD_NET_WEIGHT, FIELD_PREFERABLE_STORAGE_LOCATION, FIELD_STACKING_RULES, FIELD_DETAILS).toList();
/** The persistent unique key. */
@JsonProperty(FIELD_PKEY)
@NotEmpty(message = "{owms.wms.inv.product.pKey}", groups = ValidationGroups.UpdateProduct.class)
private String pKey;
/** The product id is part of the unique business key. */
@JsonProperty(FIELD_SKU)
@NotEmpty(message = "{owms.wms.inv.product.sku}", groups = ValidationGroups.CreateProduct.class)
private String sku;
/** An identifying label of the {@code Product}. */
@JsonProperty(FIELD_LABEL)
private String label;
/** The name of the {@code Account} the {@code Product} belongs to. */
@JsonProperty(FIELD_ACCOUNT_ID)
private String accountId;
/** {@code Product}s may be defined with different base units. */
@JsonProperty(FIELD_BASE_UNIT)
@NotNull(message = "{owms.wms.inv.product.baseUnit}", groups = ValidationGroups.CreateProduct.class)
private Measurable baseUnit;
/** Is it allowed to receive a higher quantity as expected/announced of this Product? */
@JsonProperty(FIELD_OVERBOOKING_ALLOWED)
private Boolean overbookingAllowed;
/** Textual descriptive text. */
@JsonProperty(FIELD_DESCRIPTION)
private String description;
/** The {@code Product} definition can be set to be unavailable for further operations. */
@JsonProperty(FIELD_AVAILABILITY_STATE)
private AvailabilityState availabilityState;
/** Products may be classified, e.g. hazardous. */
@JsonProperty(FIELD_CLASSIFICATION)
private String classification;
/** {@code Product}s may be grouped. */
@JsonProperty(FIELD_GROUP)
private String group;
/** Where the {@code Product} has to be placed in stock. */
@JsonProperty(FIELD_STOCK_ZONE)
private String stockZone;
/** A {@code Product} can be packed and stored in different box sizes. */
@JsonManagedReference
@JsonProperty(FIELD_UNITS)
public List<UomRelationVO> units;
/** The defined dimension of the {@code Product} in it's {@code baseUnit}. */
@JsonProperty(FIELD_DIMENSION)
private DimensionVO dimension;
/** The defined net weight of the {@code Product}. */
@JsonProperty(FIELD_NET_WEIGHT)
private Weight netWeight;
/** What is typically the preferable {@code Location} where the {@code Product} shall be stored. */
@JsonProperty(FIELD_PREFERABLE_STORAGE_LOCATION)
private LocationVO preferableStorageLocation;
/** A list of rules that define what kind of {@code Product} can be stacked on top of this one. */
@JsonManagedReference
@JsonProperty(FIELD_STACKING_RULES)
private List<StackingRuleVO> stackingRules;
/** Arbitrary detail information on this {@code Product}, might be populated with ERP information. */
@JsonProperty(FIELD_DETAILS)
private Map<String, String> details;
public String skuAndLabel() {
return sku + (label == null ? "/--" : "/"+label);
}
@Override
public String toString() {
return sku;
}
@JsonCreator
public ProductVO() {
}
public ProductVO(String sku) {
this.sku = sku;
}
private ProductVO(Builder builder) {
setpKey(builder.pKey);
setSku(builder.sku);
setLabel(builder.label);
setAccountId(builder.accountId);
setBaseUnit(builder.baseUnit);
setOverbookingAllowed(builder.overbookingAllowed);
setDescription(builder.description);
setAvailabilityState(builder.availabilityState);
setClassification(builder.classification);
setGroup(builder.group);
setStockZone(builder.stockZone);
setUnits(builder.units);
setDimension(builder.dimension);
setNetWeight(builder.netWeight);
setPreferableStorageLocation(builder.preferableStorageLocation);
setStackingRules(builder.stackingRules);
setDetails(builder.details);
}
public static Builder newBuilder() {
return new Builder();
}
public String getpKey() {
return pKey;
}
public void setpKey(String pKey) {
this.pKey = pKey;
}
public String getSku() {
return sku;
}
public void setSku(String sku) {
this.sku = sku;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getAccountId() {
return accountId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public Measurable getBaseUnit() {
return baseUnit;
}
public void setBaseUnit(Measurable baseUnit) {
this.baseUnit = baseUnit;
}
public Boolean getOverbookingAllowed() {
return overbookingAllowed;
}
public void setOverbookingAllowed(Boolean overbookingAllowed) {
this.overbookingAllowed = overbookingAllowed;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public AvailabilityState getAvailabilityState() {
return availabilityState;
}
public void setAvailabilityState(AvailabilityState availabilityState) {
this.availabilityState = availabilityState;
}
public String getClassification() {
return classification;
}
public void setClassification(String classification) {
this.classification = classification;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public String getStockZone() {
return stockZone;
}
public void setStockZone(String stockZone) {
this.stockZone = stockZone;
}
public List<UomRelationVO> getUnits() {
return units;
}
public void setUnits(List<UomRelationVO> units) {
this.units = units;
}
public DimensionVO getDimension() {
return dimension;
}
public void setDimension(DimensionVO dimension) {
this.dimension = dimension;
}
public Weight getNetWeight() {
return netWeight;
}
public void setNetWeight(Weight netWeight) {
this.netWeight = netWeight;
}
public LocationVO getPreferableStorageLocation() {
return preferableStorageLocation;
}
public void setPreferableStorageLocation(LocationVO preferableStorageLocation) {
this.preferableStorageLocation = preferableStorageLocation;
}
public List<StackingRuleVO> getStackingRules() {
return stackingRules;
}
public void setStackingRules(List<StackingRuleVO> stackingRules) {
this.stackingRules = stackingRules;
}
public Map<String, String> getDetails() {
return details;
}
public void setDetails(Map<String, String> details) {
this.details = details;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
var productVO = (ProductVO) o;
return Objects.equals(pKey, productVO.pKey) && Objects.equals(sku, productVO.sku) && Objects.equals(label, productVO.label) && Objects.equals(accountId, productVO.accountId) && Objects.equals(baseUnit, productVO.baseUnit) && Objects.equals(description, productVO.description) && availabilityState == productVO.availabilityState && Objects.equals(classification, productVO.classification) && Objects.equals(group, productVO.group) && Objects.equals(stockZone, productVO.stockZone) && Objects.equals(units, productVO.units) && Objects.equals(dimension, productVO.dimension) && Objects.equals(stackingRules, productVO.stackingRules) && Objects.equals(details, productVO.details);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), pKey, sku, label, accountId, baseUnit, description, availabilityState, classification, group, stockZone, units, dimension, stackingRules, details);
}
public static final class Builder {
private String pKey;
private String sku;
private String label;
private String accountId;
private Measurable baseUnit;
private Boolean overbookingAllowed;
private String description;
private AvailabilityState availabilityState;
private String classification;
private String group;
private String stockZone;
private List<UomRelationVO> units;
private DimensionVO dimension;
private Weight netWeight;
private LocationVO preferableStorageLocation;
private List<StackingRuleVO> stackingRules;
private Map<String, String> details;
private Builder() {
}
public Builder pKey(String val) {
pKey = val;
return this;
}
public Builder sku(String val) {
sku = val;
return this;
}
public Builder label(String val) {
label = val;
return this;
}
public Builder accountId(String val) {
accountId = val;
return this;
}
public Builder baseUnit(Measurable val) {
baseUnit = val;
return this;
}
public Builder overbookingAllowed(Boolean val) {
overbookingAllowed = val;
return this;
}
public Builder description(String val) {
description = val;
return this;
}
public Builder availabilityState(AvailabilityState val) {
availabilityState = val;
return this;
}
public Builder classification(String val) {
classification = val;
return this;
}
public Builder group(String val) {
group = val;
return this;
}
public Builder stockZone(String val) {
stockZone = val;
return this;
}
public Builder units(List<UomRelationVO> val) {
units = val;
return this;
}
public Builder addUnit(UomRelationVO val) {
if (units == null) {
units = new ArrayList<>();
}
units.add(val);
return this;
}
public Builder dimension(DimensionVO val) {
dimension = val;
return this;
}
public Builder netWeight(Weight val) {
netWeight = val;
return this;
}
public Builder preferableStorageLocation(LocationVO val) {
preferableStorageLocation = val;
return this;
}
public Builder stackingRules(List<StackingRuleVO> val) {
stackingRules = val;
return this;
}
public Builder details(Map<String, String> val) {
details = val;
return this;
}
public ProductVO build() {
return new ProductVO(this);
}
}
}