/*
* Copyright (C) 2014 GG-Net GmbH - Oliver Günther
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.ggnet.dwoss.uniqueunit.entity;
import java.io.*;
import java.text.DateFormat;
import java.util.*;
import javax.persistence.*;
import javax.validation.constraints.*;
import eu.ggnet.dwoss.rules.*;
import eu.ggnet.dwoss.util.*;
import eu.ggnet.dwoss.util.persistence.EagerAble;
import lombok.*;
import static eu.ggnet.dwoss.uniqueunit.entity.UniqueUnit.Equipment.*;
import static eu.ggnet.dwoss.uniqueunit.entity.UniqueUnit.Identifier.REFURBISHED_ID;
import static javax.persistence.CascadeType.*;
/**
* A UniqueUnit represents exactly one unit that is unique in the whole system.
* Identefiable through {@link Identifier}
*
* @has n - 1 Product
* @has 1 - n UniqueUnitHistory
* @has n - m UniqueUnit.Equipment
* @has n - m UniqueUnit.StaticComment
* @has n - m UniqueUnit.StaticInternalComment
* @has n - 1 UniqueUnit.Condition
* @has 1 - n PriceHistory
* @has 1 - 1 Identifier
* @has n - m Flag
*/
@Entity
@NoArgsConstructor
@EqualsAndHashCode(of = {"id"})
@NamedQueries({
// HINT: Netbeans Warinig is wrong. 2. HINT: Hibernate builds defective Query.
@NamedQuery(name = "UnqiueUnit.findByIdenfiersTypeValue", query = "SELECT u FROM UniqueUnit u join u.identifiers i WHERE KEY(i) = ?1 and VALUE(i) IN (?2)"),
@NamedQuery(name = "UnqiueUnit.betweenInputDates", query = "SELECT u FROM UniqueUnit u WHERE u.inputDate >= ?1 AND u.inputDate <= ?2"),
@NamedQuery(name = "UnqiueUnit.betweenInputDatesAndContractor", query = "SELECT u FROM UniqueUnit u WHERE u.inputDate >= ?1 AND u.inputDate <= ?2 and u.contractor = ?3"),
@NamedQuery(name = "UniqueUnit.findByIds", query = "SELECT u FROM UniqueUnit u WHERE u.id IN (:idList)"),
@NamedQuery(name = "UniqueUnit.byProductPartNo", query = "SELECT u FROM UniqueUnit u WHERE u.product.partNo = ?1"),
@NamedQuery(name = "UniqueUnit.byProductPartNosInputDate", query = "SELECT u FROM UniqueUnit u WHERE u.product.partNo in (?1) AND u.inputDate >= ?2 AND u.inputDate <= ?3"),
@NamedQuery(name = "UnqiueUnit.byContractor", query = "SELECT u FROM UniqueUnit u WHERE u.contractor = ?1"),
@NamedQuery(name = "UniqueUnit.countByInputDateContractor",
query = "select new eu.ggnet.dwoss.uniqueunit.eao.CountHolder(u.inputDate, u.product.tradeName, u.contractor, count(u.id)) "
+ "from UniqueUnit u where u.inputDate >= :start and u.inputDate <= :end GROUP BY u.contractor, u.product.tradeName, cast(u.inputDate as date)")
})
public class UniqueUnit implements Serializable, EagerAble {
public static NavigableMap<String, UniqueUnit> asMapByRefurbishId(Collection<UniqueUnit> uus) {
NavigableMap<String, UniqueUnit> result = new TreeMap<>();
for (UniqueUnit uu : uus) {
result.put(uu.getIdentifier(REFURBISHED_ID), uu);
}
return result;
}
private final static DateFormat MEDIUM = DateFormat.getDateInstance(DateFormat.MEDIUM);
/**
* The equipment parts a UniqueUnit may have.
*/
public static enum Equipment implements INoteModel {
POWER_CABLE("Stromkabel"),
PLUGIN_AC_ADAPTER("Steckernetzteil"), // NB
AC_ADAPTER_INC_CABLE("Netzteil inkl. Stromkabel"), //NB
BATTERY("Akku"),
REMOTE("Fernbedienung"),
EXT_ANTENNA("externe Antenne"),
KEYBOARD("Tastatur"),
MOUSE("Maus"),
GAME_KEYBOARD("Gaming-Tastatur"),
GAME_MOUSE("Gaming-Maus"),
CABLELES_KEYBOARD("Funktastatur"),
CABLELES_MOUSE("Funkmaus"),
ANTENNA_ADAPTER("Antennenadapter"),
DONGLE("Dongle"),
INSTALL_DISCS("Installations CDs"),
VGA_CABLE("VGA-Kabel"),
DVI_CABLE("DVI-Kabel"),
HDMI_CABLE("HDMI-Kabel"),
FOOT("Fuß"),
DISPLAY_FOOT_CONNECTOR("Bein"),
THREE_D_GLASSES("3D Brille"),
ORIGINAL_BOXED("Original Karton"),
KEYBOARD_DOCK("Dockingstation mit Tastatur"),
USB_KABEL("USB-Kabel"),
VGA_NETWORK_ADAPTER("VGA-/Netzwerkadapter"),
MICRO_USB_TO_USB_ADAPTER("Micro USB - USB Adapter"),
WLAN_KINK_ANTENNA("WLAN Knickantenne"),
PORTFOLIO_CASE("Portfolio Case"),
SDCARD_16GB("16GB SD Karte"),
HDMI_VGA_ADAPTER("HDMI-VGA Adapter"),
USB_NETWORK_ADAPTER("USB Netzwerk Adapter"),
PORTFOLIO_CASE_INTEGRATED_KEYBOARD("Portfolio Case inkl. Tastatur"),
SIM_OPENER("SIM-Kartenöffner"),
WALLHOLDER("Wandhalterung"),
VGA_USB_NETWORK_ADAPTER("VGA-/USB-/Netzwerk Adapter"),
USB_MICRO_HDMI_ADAPTER("USB- Micro HDMI Adapter"),
ALTERNATIBVE_USB_CABLE("alternativ USB-Kabel"),
HEADSET("Headset"),
HEADPHONE("Kopfhörer"),
DVI_HDMI_ADAPTOR("DVI-HDMI Adapter"),
MANUAL("Bedienungsanleitung"),
ALTERNATIVE_BOXED("Alternativverpackung"),
CRUNCHCOVER("Crunchcover"),
ALTERNATIVE_PLUGIN_AC_ADAPTER("Alternativsteckernetzteil"),
MS_OFFICE_365_PERSONAL("Microsoft Office 365 Personal inkl."),
MS_OFFICE_HOME_AND_STUDENT_2013("Microsoft Office Home and Student 2013 inkl."),
STYLUS("Stylus / Displaystift"),
DISPLAYPORT_CABLE("Displayportkabel"),
VGA_USB_ADAPTER("VGA-USB Adapter"),
MAGNETIC_CHARGING_CABLE("magnetisches Ladekabel"),
SPARE_STRAP("Ersatzarmband");
private final String note;
private final double economicValue;
private Equipment(String note) {
this(note, 0);
}
private Equipment(String note, double economicValue) {
this.note = note;
this.economicValue = economicValue;
}
@Override
public String getNote() {
return note;
}
public double getEconomicValue() {
return economicValue;
}
public static Set<Equipment> getEquipments() {
return getEquipments(null);
}
/**
* Returns a Set of Equipment filtered by the {@link ProductGroup}.
* <p/>
* @param group the {@link ProductGroup}
* @return a Set of Equipment filtered by the {@link ProductGroup}.
*/
public static Set<Equipment> getEquipments(ProductGroup group) {
if ( group == null ) {
return EnumSet.allOf(Equipment.class);
}
switch (group) {
case TV:
return EnumSet.of(ORIGINAL_BOXED, ALTERNATIVE_BOXED, POWER_CABLE, HDMI_CABLE, FOOT, DISPLAY_FOOT_CONNECTOR,
THREE_D_GLASSES, REMOTE, MANUAL, ALTERNATIVE_PLUGIN_AC_ADAPTER, ALTERNATIBVE_USB_CABLE);
case ALL_IN_ONE:
return EnumSet.of(ORIGINAL_BOXED, ALTERNATIVE_BOXED, POWER_CABLE, MOUSE, KEYBOARD, GAME_MOUSE, GAME_KEYBOARD, CABLELES_KEYBOARD, CABLELES_MOUSE, ANTENNA_ADAPTER,
DONGLE, FOOT, DISPLAY_FOOT_CONNECTOR, THREE_D_GLASSES, REMOTE, AC_ADAPTER_INC_CABLE, WALLHOLDER, MANUAL, ALTERNATIVE_PLUGIN_AC_ADAPTER,
ALTERNATIBVE_USB_CABLE, USB_KABEL);
case DESKTOP_BUNDLE:
Set<Equipment> equipments = getEquipments(ProductGroup.DESKTOP);
equipments.addAll(getEquipments(ProductGroup.MONITOR));
return equipments;
case SERVER:
return EnumSet.of(ORIGINAL_BOXED, ALTERNATIVE_BOXED, POWER_CABLE, MOUSE, KEYBOARD, MANUAL, ALTERNATIVE_PLUGIN_AC_ADAPTER, ALTERNATIBVE_USB_CABLE);
case DESKTOP:
return EnumSet.of(ORIGINAL_BOXED, ALTERNATIVE_BOXED, POWER_CABLE, MOUSE, KEYBOARD, GAME_MOUSE, GAME_KEYBOARD, CABLELES_KEYBOARD, MANUAL, ALTERNATIBVE_USB_CABLE,
CABLELES_MOUSE, ANTENNA_ADAPTER, DONGLE, AC_ADAPTER_INC_CABLE, FOOT, WLAN_KINK_ANTENNA, DVI_HDMI_ADAPTOR, ALTERNATIVE_PLUGIN_AC_ADAPTER);
case MONITOR:
return EnumSet.of(ORIGINAL_BOXED, ALTERNATIVE_BOXED, POWER_CABLE, AC_ADAPTER_INC_CABLE, VGA_CABLE, DVI_CABLE, HDMI_CABLE, FOOT,
DISPLAY_FOOT_CONNECTOR, THREE_D_GLASSES, USB_KABEL, MANUAL, ALTERNATIVE_PLUGIN_AC_ADAPTER, ALTERNATIBVE_USB_CABLE, DISPLAYPORT_CABLE);
case TABLET_SMARTPHONE:
return EnumSet.of(ORIGINAL_BOXED, ALTERNATIVE_BOXED, PLUGIN_AC_ADAPTER, AC_ADAPTER_INC_CABLE, BATTERY, USB_KABEL, KEYBOARD_DOCK, VGA_NETWORK_ADAPTER, HEADSET, MANUAL,
MICRO_USB_TO_USB_ADAPTER, PORTFOLIO_CASE, SDCARD_16GB, HDMI_VGA_ADAPTER, USB_NETWORK_ADAPTER, PORTFOLIO_CASE, USB_MICRO_HDMI_ADAPTER, SIM_OPENER,
PORTFOLIO_CASE_INTEGRATED_KEYBOARD, CRUNCHCOVER, ALTERNATIVE_PLUGIN_AC_ADAPTER, ALTERNATIBVE_USB_CABLE, MS_OFFICE_365_PERSONAL,
MS_OFFICE_HOME_AND_STUDENT_2013, STYLUS,MAGNETIC_CHARGING_CABLE,SPARE_STRAP);
case NOTEBOOK:
return EnumSet.of(ORIGINAL_BOXED, ALTERNATIVE_BOXED, PLUGIN_AC_ADAPTER, AC_ADAPTER_INC_CABLE, BATTERY, REMOTE, EXT_ANTENNA, THREE_D_GLASSES, MANUAL, DONGLE,
VGA_NETWORK_ADAPTER, CABLELES_MOUSE, HDMI_VGA_ADAPTER, USB_NETWORK_ADAPTER, PORTFOLIO_CASE, VGA_USB_NETWORK_ADAPTER, SIM_OPENER,
PORTFOLIO_CASE_INTEGRATED_KEYBOARD, ALTERNATIVE_PLUGIN_AC_ADAPTER, ALTERNATIBVE_USB_CABLE, KEYBOARD_DOCK, MS_OFFICE_365_PERSONAL,
MS_OFFICE_HOME_AND_STUDENT_2013, STYLUS, USB_KABEL, VGA_USB_ADAPTER,MAGNETIC_CHARGING_CABLE);
default:
}
return EnumSet.allOf(Equipment.class);
}
}
/**
* Most common standart notes that a unit may have.
*/
public static enum StaticComment implements INoteModel {
FRONT_COVER_MISSING("Untere Fronklappe fehlt"),
USED_KEABOARD("abgenutzte Tastatur"),
USED_TOUCHPAD("abgenutztes Touchpad"),
SCRATCHES_DISPLAYCOVER("Kratzer auf dem Displayrahmen"),
SCRATCHES_DISPLAY("Kratzer auf dem Display"),
DISPLAY_PIXERROR("Pixelfehler festgestellt"),
SCRATCHES_COVER("Kratzer auf dem Deckel"),
SCRATCHES_KEYBOARD("Kratzer um die Tastatur"),
SCRATCHES_TOUCH("Kratzer um das Touchpad"),
USETRACES_DISPLAYCOVER("Gebrauchsspuren auf dem Displayrahmen"),
USETRACES_COVER("Gebrauchsspuren auf dem Deckel"),
USETRACES_TOUCH("Gebrauchsspuren um die Tastatur"),
USETRACES_KEYBOARD("Gebrauchsspuren um das Touchpad"),
SCRATCHES_CASE("Kratzer auf dem Gehäuse"),
DENT_SOUND("Delle/n auf der Lautsprecherabdeckung"),
DENT_COVER("Delle/n auf dem Deckel"),
DENT_CASE("Delle/n auf dem Gehäuse"),
MINIMAL_USETRACES_COVER("minimale Gebrauchsspuren auf dem Deckel"),
USETRACES_ABOVE_KEYBOARD("Gebrauchsspuren über der Tastatur"),
SMALL_USETRACES_ABOVE_KEYBOARD("leichte Gebrauchsspuren über der Tastatur"),
SCRATCHES_ABOVE_KEYBOARD("Kratzer über der Tastatur"),
SCRATCHES_ON_CASE_SIDE("Kratzer auf dem Gehäuserand"),
SCRATCHES_ON_CASE_BOTTOM_SIDE("Kratzer auf der Geräteunterseite"),
USETRACES_AROUND_KEYBOARD("Kratzer am Gehäuserand um die Tastatur"),
SIGNIFICANT_TRACES_AROUND_TOUCH("deutliche Gebrauchsspuren um das Touchpad"),
SLIGHT_USETRACES_COVER("leichte Gebrauchsspuren auf dem Deckel"),
SCRATCHES_ON_CASE_BELOW_KEABOARD("Kratzer am Gehäuserand unter der Tastatur."),
SLIGHT_USETRACES_AROUND_TOUCH("leichte Gebrauchsspuren um das Touchpad"),
MINIMAL_USETRACES_AROUND_TOUCH("minimale Gebrauchsspuren um das Touchpad"),
SIGNIFICANT_SCRATCHES_COVER("deutliche Kratzer auf dem Deckel"),
SIGNIFICANT_SCRATCHES_DISPLAYCOVER("deutliche Kratzer auf dem Displayrahmen"),
SIGNIFICANT_SCRATCHES_AROUND_KEYBOARD("deutliche Kratzer um die Tastatur"),
SIGNIFICANT_SCRATCHES_KEYBOARD("deutliche Kratzer über der Tastatur"),
SIGNIFICANT_USETRACES_DISPLAYCOVER("deutliche Gebrauchsspuren auf dem Displayrahmen"),
SIGNIFICANT_USETRACES_COVER("deutliche Gebrauchsspuren auf dem Deckel"),
SCRATCHES_ON_COVER_EDGE("Kratzer am Deckelrand"),
SCRATCHES_ON_TOUCH("Kratzer auf dem Touchpad"),
SLIGHT_SCRATCHES_ON_DISPLAYCOVER("leichte Kratzer auf dem Displayrahmen"),
SCRATCHES_ON_THE_BACK("Kratzer auf der Geräterückseite"),
USETRACES_ON_THE_BACK("Gebrauchsspuren auf der Geräterückseite"),
SLIGHT_USETRACES_ON_DISPLAYCOVER("leichte Gebrauchsspuren auf dem Displayrahmen"),
SLIGHT_SCRATCHES_ON_COVER("leichte Kratzer auf dem Deckel"),
SIGNIFICANT_SCRATCHES_ON_CASE("deutliche Kratzer auf dem Gehäuse"),
SLIGHT_SCRATCHES_ON_CASE("leichte Kratzer auf dem Gehäuse"),
SCRATCHES_ON_FOOT("Kratzer auf dem Fuß"),
FOREIGN_PARTICLES_BELOW_DISPLAY("Fremdpartikel unter dem Display"),
SLIGHT_SCRATCHES_ON_CASE_BOTTOM_SIDE("leichte Kratzer auf der Geräteunterseite"),
SCRATCHES_ON_DISPLAY_STAND("Kratzer auf dem Displaybein"),
SCRATCHES_BELOW_KEYBOARD("Kratzer unterhalb der Tastatur"),
REMAINS_OF_GLUE_BOTTOM_SIDE("Klebereste auf der Geräteunterseite"),
SLIGHT_SCRATCHES_AROUND_TOUCHPAD("leichte Kratzer um das Touchpad"),
USETRACES_ON_CASE_BOTTOM_SIDE("Gebrauchsspuren auf der Geräteunterseite"),
USETRACES_DISPLAY("Gebrauchsspuren auf dem Display");
private final String note;
private final double economicValue;
private StaticComment(String note) {
this(note, 0);
}
private StaticComment(String note, double economicValue) {
this.note = note;
this.economicValue = economicValue;
}
@Override
public String getNote() {
return note;
}
public double getEconomicValue() {
return economicValue;
}
}
/**
* Most common internal notes that a unit may have.
*/
public static enum StaticInternalComment implements INoteModel {
/**
* Prepared for Shipping ("versandfertig").
*/
PREPARED_SHIPMENT("Versandfertig"),
D_PARTITION_CHECKED("D Partition geprüft"),
CLEANED("Gerät gereinigt"),
RECOVERT("Gerät recovert"),
REMOVED_OS("OS gelöscht"),
EXTERNAL_GPU_SEEN("Externe Grafikkarte gesehen"),
HDD_CASE("Festplattenhalterungen gesehen"),
CHANGED_CONFIGURATION("geänderte Konfiguration"),
REFILLED("Komponenten aufgefüllt"),
DONGLE_INSIDE_MOUSE("Dongle in der Maus");
private final String note;
private final double economicValue;
private StaticInternalComment(String note) {
this(note, 0);
}
private StaticInternalComment(String note, double economicValue) {
this.note = note;
this.economicValue = economicValue;
}
@Override
public String getNote() {
return note;
}
public double getEconomicValue() {
return economicValue;
}
}
/**
* Possible states every unit is categorized in.
*/
public enum Condition implements INoteModel {
AS_NEW("neuwertig"),
ALMOST_NEW("nahezu neuwertig"),
USED("gebraucht");
private final String note;
private final double economicValue;
private Condition(String note) {
this(note, 0);
}
private Condition(String note, double economicValue) {
this.note = note;
this.economicValue = economicValue;
}
@Override
public String getNote() {
return note;
}
public double getEconomicValue() {
return economicValue;
}
}
/**
* The possible identifiers for exactly one unit.
*/
public enum Identifier {
SERIAL, REFURBISHED_ID
}
public static enum Flag {
PRICE_FIXED
}
/**
* Classification inspired by Also.
* <p/>
* @deprecated Cooperation with Also has been canceled, may be removed.
*/
@RequiredArgsConstructor
@Getter
@Deprecated
public static enum BnClassification {
B0_UNDEFINED("B0 - Keine Klassifikation"),
B1_NEW("B1 - Vergleichbar mit Neuware"),
B2_AS_NEW("B2 - Neuwertig und Vollständig"),
B3_USED("B3 - Gebraucht und Verkaufsfähig"),
B4_USED("B4 - Gebraucht und Unvollständig"),
B5_BROCKEN("B5 - Beschädigt"),
B6_CHEAP("B6 - Wert unter 25,- €");
private final String name;
}
@Getter
@Id
@GeneratedValue
private int id;
@Version
private short optLock;
@OneToMany(cascade = ALL, mappedBy = "uniqueUnit", fetch = FetchType.EAGER)
private Set<UniqueUnitHistory> history = new HashSet<>();
@ElementCollection(fetch = FetchType.EAGER)
@MapKeyEnumerated
private Map<Identifier, String> identifiers = new EnumMap<>(Identifier.class);
// No Merge, Product may change while a UniqueUnit is detached.
@NotNull
@ManyToOne(cascade = {PERSIST, REFRESH, DETACH}, fetch = FetchType.EAGER)
private Product product;
@NotNull
@ElementCollection(fetch = FetchType.EAGER)
@MapKeyEnumerated
private Map<PriceType, Double> prices = new EnumMap<>(PriceType.class);
@NotNull
@OneToMany(cascade = ALL)
private List<PriceHistory> priceHistories = new ArrayList<>();
@Getter
@Setter
@ElementCollection
private Set<Equipment> equipments = EnumSet.noneOf(Equipment.class);
/**
* Represents Flags the user can set for this element. This is a better
* idea, than creating multiple boolean values.
*/
//TODO: There is only one flag so a single boolean would be okay - PP
@Getter
@Setter
@NotNull
@ElementCollection(fetch = FetchType.EAGER)
private Set<Flag> flags = EnumSet.noneOf(Flag.class);
@Getter
@Setter
@ElementCollection
private Set<StaticComment> comments = EnumSet.noneOf(StaticComment.class);
@Getter
@Setter
@ElementCollection
private Set<StaticInternalComment> internalComments = EnumSet.noneOf(StaticInternalComment.class);
@Getter
@Setter
@NotNull
@Column(name = "uniqueUnitCondition")
private Condition condition;
@NotNull
private TradeName contractor;
public TradeName getContractor() {
return contractor;
}
public void setContractor(TradeName contractor) {
this.contractor = contractor;
}
@Getter
@Setter
@Past
@Temporal(TemporalType.DATE)
private Date mfgDate;
@Getter
@Setter
@Basic
@Lob
@Column(length = 65536)
private String comment;
@Getter
@Setter
@Basic
@Lob
@Column(length = 65536)
private String internalComment;
@Getter
@Setter
private long shipmentId;
@Getter
private String shipmentLabel;
@Getter
@Setter
@NotNull
@Basic(optional = false)
private SalesChannel salesChannel = SalesChannel.UNKNOWN;
@Getter
@Setter
@Temporal(TemporalType.TIMESTAMP)
@Column(columnDefinition = "DATETIME")
private Date inputDate;
@Getter
@Setter
@NotNull
private Warranty warranty = Warranty.ONE_YEAR_CARRY_IN;
@Getter
@Setter
@Temporal(TemporalType.DATE)
private Date warrentyValid;
/**
* Also Classifiaction.
* <p/>
* @deprecated Cooperation with Also has been canceled, may be removed.
*/
@Getter
@Setter
@NotNull
@Deprecated
private BnClassification classification = BnClassification.B0_UNDEFINED;
/**
* A non Productive Constructor.
* <p/>
* @param id
*/
UniqueUnit(int id) {
this.id = id;
}
public UniqueUnit(int id, Date mfgDate, String comment) {
this.id = id;
this.mfgDate = mfgDate;
this.comment = comment;
}
@SuppressWarnings("OverridableMethodCallInConstructor")
public UniqueUnit(Product product, Date mfgDate, String comment) {
this.mfgDate = mfgDate;
this.comment = comment;
setProduct(product);
}
public UniqueUnit(Date mfgDate, String comment) {
this.mfgDate = mfgDate;
this.comment = comment;
}
public void setPrice(PriceType type, double price, String comment) {
if ( MathUtil.equals(getPrice(type), price) ) {
return; // Don't set the same price
}
prices.put(type, price);
priceHistories.add(new PriceHistory(type, price, new Date(), comment));
}
public boolean hasPrice(PriceType type) {
return prices.get(type) != null && prices.get(type) > 0.01;
}
public double getPrice(PriceType type) {
return prices.get(type) == null ? 0 : prices.get(type);
}
public Map<PriceType, Double> getPrices() {
return Collections.unmodifiableMap(prices);
}
public boolean removeFlag(Flag flag) {
return flags.remove(flag);
}
public boolean addFlag(Flag flag) {
return flags.add(flag);
}
public List<PriceHistory> getPriceHistory() {
return priceHistories;
}
public String getIdentifier(Identifier type) {
return identifiers.get(type);
}
public String getRefurbishId() {
return identifiers.get(Identifier.REFURBISHED_ID);
}
public String getSerial() {
return identifiers.get(Identifier.SERIAL);
}
public Map<Identifier, String> getIdentifiers() {
return Collections.unmodifiableMap(identifiers);
}
public void setIdentifier(final Identifier type, final String identifier) {
if ( this.identifiers.containsKey(type) && Objects.equals(this.identifiers.get(type), identifier) ) {
return;
}
addHistory(UniqueUnitHistory.Type.UNIQUE_UNIT, type + " set to " + identifier);
this.identifiers.put(type, identifier);
}
public void setShipmentLabel(String shipmentLabel) {
if ( Objects.equals(this.shipmentLabel, shipmentLabel) ) {
return;
}
addHistory(UniqueUnitHistory.Type.UNIQUE_UNIT, "Setting Shipment from " + this.shipmentLabel + " to " + shipmentLabel);
this.shipmentLabel = shipmentLabel;
}
public Set<UniqueUnitHistory> getHistory() {
return Collections.unmodifiableSet(history);
}
public void addHistory(UniqueUnitHistory uniqueUnitHistory) {
uniqueUnitHistory.uniqueUnit = this;
history.add(uniqueUnitHistory);
}
public void addHistory(UniqueUnitHistory.Type type, String comment) {
addHistory(new UniqueUnitHistory(type, comment));
}
public void addHistory(String comment) {
addHistory(new UniqueUnitHistory(UniqueUnitHistory.Type.UNDEFINED, comment));
}
public Product getProduct() {
return product;
}
/**
* Sets the {@link Product} in consideration of equalancy and bidirectional
* behaviour.
* <p/>
* @param product
*/
public void setProduct(Product product) {
if ( product == null && this.product == null ) {
return;
}
if ( this.product != null && this.product.equals(product) ) {
return;
}
if ( this.product != null ) {
this.product.units.remove(this);
}
if ( product != null ) {
product.units.add(this);
}
this.product = product;
}
@Override
public String toString() {
String productString = null;
String formatedMfgDate = null;
String formatedInputDate = null;
if ( product != null ) {
productString = "[" + product.getPartNo() + "]" + product.getTradeName() + " " + product.getName();
}
if ( mfgDate != null ) {
formatedMfgDate = DateFormats.ISO.format(mfgDate);
}
if ( inputDate != null ) {
formatedInputDate = MEDIUM.format(inputDate);
}
return "UniqueUnit{" + "id=" + id + ", identifiers=" + identifiers + ", product=" + productString + ", prices=" + prices + ", equipments=" + equipments
+ ", flags=" + flags + ", comments=" + comments + ", internalComments=" + internalComments + ", condition=" + condition
+ ", contractor=" + contractor + ", mfgDate=" + formatedMfgDate + ", shipmentId=" + shipmentId + ", shipmentLabel=" + shipmentLabel
+ ", salesChannel=" + salesChannel + ", inputDate=" + formatedInputDate + ", warranty=" + warranty + ", classification=" + classification
+ ", comment=" + comment + ", internalComment=" + internalComment + '}';
}
/**
* Calls all m-n Relations recursive to ensure, that this instance works
* detached.
*/
@Override
public void fetchEager() {
if ( getProduct() != null ) {
getProduct().getName();
}
getComments().size();
getInternalComments().size();
getEquipments().size();
getHistory().size();
getPriceHistory().size();
}
}