SHA-256
then encode it with Base64.
+ *
+ * @param plainTextPassword the password to digest and encode
+ * @return digested password
+ */
+ public static String digestPassword(String plainTextPassword)
+ {
+ try
+ {
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
+ md.update(plainTextPassword.getBytes("UTF-8"));
+ byte[] passwordDigest = md.digest();
+ return Base64.getEncoder().encodeToString(passwordDigest);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Exception encoding password", e);
+ }
+ }
+
+ // ======================================
+ // = Getters & setters =
+ // ======================================
+
+ public Long getId()
+ {
+ return this.id;
+ }
+
+ public void setId(final Long id)
+ {
+ this.id = id;
+ }
+
+ public int getVersion()
+ {
+ return this.version;
+ }
+
+ public void setVersion(final int version)
+ {
+ this.version = version;
+ }
+
+ public String getLogin()
+ {
+ return login;
+ }
+
+ public void setLogin(String login)
+ {
+ this.login = login;
+ }
+
+ public UserRole getRole()
+ {
+ return role;
+ }
+
+ public void setRole(UserRole role)
+ {
+ this.role = role;
+ }
+
+ public String getUuid()
+ {
+ return uuid;
+ }
+
+ public void setUuid(String uuid)
+ {
+ this.uuid = uuid;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ public String getFirstName()
+ {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName)
+ {
+ this.firstName = firstName;
+ }
+
+ public String getLastName()
+ {
+ return lastName;
+ }
+
+ public void setLastName(String lastName)
+ {
+ this.lastName = lastName;
+ }
+
+ public String getFullName()
+ {
+ return firstName + " " + lastName;
+ }
+
+ public String getTelephone()
+ {
+ return telephone;
+ }
+
+ public void setTelephone(String telephone)
+ {
+ this.telephone = telephone;
+ }
+
+ public String getEmail()
+ {
+ return email;
+ }
+
+ public void setEmail(String email)
+ {
+ this.email = email;
+ }
+
+ public Date getDateOfBirth()
+ {
+ return dateOfBirth;
+ }
+
+ public void setDateOfBirth(Date dateOfBirth)
+ {
+ this.dateOfBirth = dateOfBirth;
+ }
+
+ public Integer getAge()
+ {
+ return age;
+ }
+
+ public Address getHomeAddress()
+ {
+ return homeAddress;
+ }
+
+ public void setHomeAddress(Address homeAddress)
+ {
+ this.homeAddress = homeAddress;
+ }
+
+ // ======================================
+ // = Methods hash, equals, toString =
+ // ======================================
+
+ @Override
+ public final boolean equals(Object o)
+ {
+ if (this == o)
+ return true;
+ if (!(o instanceof Customer))
+ return false;
+ Customer customer = (Customer) o;
+ return Objects.equals(login, customer.login);
+ }
+
+ @Override
+ public final int hashCode()
+ {
+ return Objects.hash(login);
+ }
+
+ @Override
+ public String toString()
+ {
+ return firstName + ' ' + lastName + " (" + login + ")";
+ }
+}
diff --git a/src/main/java/org/prabuckt/application/vegancakes/model/Item.java b/src/main/java/org/prabuckt/application/vegancakes/model/Item.java
new file mode 100644
index 0000000..7244f5d
--- /dev/null
+++ b/src/main/java/org/prabuckt/application/vegancakes/model/Item.java
@@ -0,0 +1,200 @@
+package org.prabuckt.application.vegancakes.model;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.prabuckt.application.vegancakes.constraints.NotEmpty;
+import org.prabuckt.application.vegancakes.constraints.Price;
+
+/**
+ * @author Tomasz Prabucki https://tprabucki.netlify.com --
+ */
+
+@Entity
+@Cacheable
+@NamedQueries({
+ @NamedQuery(name = Item.FIND_BY_PRODUCT_ID, query = "SELECT i FROM Item i WHERE i.product.id = :productId"),
+ @NamedQuery(name = Item.SEARCH, query = "SELECT i FROM Item i WHERE UPPER(i.name) LIKE :keyword OR UPPER(i.product.name) LIKE :keyword ORDER BY i.product.category.name, i.product.name"),
+ @NamedQuery(name = Item.FIND_ALL, query = "SELECT i FROM Item i")
+})
+@XmlRootElement
+public class Item implements Serializable
+{
+
+ // ======================================
+ // = Attributes =
+ // ======================================
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(name = "id", updatable = false, nullable = false)
+ private Long id;
+ @Version
+ @Column(name = "version")
+ private int version;
+
+ @Column(length = 30, nullable = false)
+ @NotNull
+ @Size(min = 1, max = 30)
+ private String name;
+
+ @Column(length = 3000, nullable = false)
+ @NotNull
+ @Size(max = 3000)
+ private String description;
+
+ @Column(name = "image_path")
+ @NotEmpty
+ private String imagePath;
+
+ @Column(name = "unit_cost", nullable = false)
+ @NotNull
+ @Price
+ private Float unitCost;
+
+ @ManyToOne(cascade = CascadeType.PERSIST)
+ @JoinColumn(name = "product_fk", nullable = false)
+ @XmlTransient
+ private Product product;
+
+ // ======================================
+ // = Constants =
+ // ======================================
+
+ public static final String FIND_BY_PRODUCT_ID = "Item.findByProductId";
+ public static final String SEARCH = "Item.search";
+ public static final String FIND_ALL = "Item.findAll";
+
+ // ======================================
+ // = Constructors =
+ // ======================================
+
+ public Item()
+ {
+ }
+
+ public Item(String name, Float unitCost, String imagePath, String description, Product product)
+ {
+ this.name = name;
+ this.unitCost = unitCost;
+ this.imagePath = imagePath;
+ this.description = description;
+ this.product = product;
+ }
+
+ // ======================================
+ // = Getters & setters =
+ // ======================================
+
+ public Long getId()
+ {
+ return this.id;
+ }
+
+ public void setId(final Long id)
+ {
+ this.id = id;
+ }
+
+ public int getVersion()
+ {
+ return this.version;
+ }
+
+ public void setVersion(final int version)
+ {
+ this.version = version;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getDescription()
+ {
+ return description;
+ }
+
+ public void setDescription(String description)
+ {
+ this.description = description;
+ }
+
+ public String getImagePath()
+ {
+ return imagePath;
+ }
+
+ public void setImagePath(String imagePath)
+ {
+ this.imagePath = imagePath;
+ }
+
+ public Float getUnitCost()
+ {
+ return unitCost;
+ }
+
+ public void setUnitCost(Float unitCost)
+ {
+ this.unitCost = unitCost;
+ }
+
+ public Product getProduct()
+ {
+ return this.product;
+ }
+
+ public void setProduct(final Product product)
+ {
+ this.product = product;
+ }
+
+ // ======================================
+ // = Methods hash, equals, toString =
+ // ======================================
+
+ @Override
+ public final boolean equals(Object o)
+ {
+ if (this == o)
+ return true;
+ if (!(o instanceof Item))
+ return false;
+ Item item = (Item) o;
+ return Objects.equals(name, item.name) &&
+ Objects.equals(description, item.description);
+ }
+
+ @Override
+ public final int hashCode()
+ {
+ return Objects.hash(name, description);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Item{" +
+ "id=" + id +
+ ", version=" + version +
+ ", name='" + name + '\'' +
+ ", description='" + description + '\'' +
+ ", imagePath='" + imagePath + '\'' +
+ ", unitCost=" + unitCost +
+ ", product=" + product +
+ '}';
+ }
+}
diff --git a/src/main/java/org/prabuckt/application/vegancakes/model/OrderLine.java b/src/main/java/org/prabuckt/application/vegancakes/model/OrderLine.java
new file mode 100644
index 0000000..0183b08
--- /dev/null
+++ b/src/main/java/org/prabuckt/application/vegancakes/model/OrderLine.java
@@ -0,0 +1,133 @@
+package org.prabuckt.application.vegancakes.model;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import javax.persistence.*;
+import javax.validation.constraints.Min;
+
+@Entity
+@Table(name = "order_line")
+public class OrderLine implements Serializable
+{
+
+ // ======================================
+ // = Attributes =
+ // ======================================
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(name = "id", updatable = false, nullable = false)
+ private Long id;
+ @Version
+ @Column(name = "version")
+ private int version;
+
+ @Column(nullable = false)
+ @Min(1)
+ private Integer quantity;
+
+ @ManyToOne(cascade = CascadeType.PERSIST)
+ @JoinColumn(name = "item_fk", nullable = false)
+ private Item item;
+
+ // ======================================
+ // = Constructors =
+ // ======================================
+
+ public OrderLine()
+ {
+ }
+
+ public OrderLine(Integer quantity, Item item)
+ {
+ this.quantity = quantity;
+ this.item = item;
+ }
+
+ // ======================================
+ // = Business methods =
+ // ======================================
+
+ public Float getSubTotal()
+ {
+ return item.getUnitCost() * quantity;
+ }
+
+ // ======================================
+ // = Getters & setters =
+ // ======================================
+
+ public Long getId()
+ {
+ return this.id;
+ }
+
+ public void setId(final Long id)
+ {
+ this.id = id;
+ }
+
+ public int getVersion()
+ {
+ return this.version;
+ }
+
+ public void setVersion(final int version)
+ {
+ this.version = version;
+ }
+
+ public Integer getQuantity()
+ {
+ return quantity;
+ }
+
+ public void setQuantity(Integer quantity)
+ {
+ this.quantity = quantity;
+ }
+
+ public Item getItem()
+ {
+ return this.item;
+ }
+
+ public void setItem(final Item item)
+ {
+ this.item = item;
+ }
+
+ // ======================================
+ // = Methods hash, equals, toString =
+ // ======================================
+
+ @Override
+ public final boolean equals(Object o)
+ {
+ if (this == o)
+ return true;
+ if (!(o instanceof OrderLine))
+ return false;
+ OrderLine orderLine = (OrderLine) o;
+ return Objects.equals(quantity, orderLine.quantity) &&
+ Objects.equals(item, orderLine.item);
+ }
+
+ @Override
+ public final int hashCode()
+ {
+ return Objects.hash(quantity, item);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "OrderLine{" +
+ "id=" + id +
+ ", version=" + version +
+ ", quantity=" + quantity +
+ ", item=" + item +
+ '}';
+ }
+}
diff --git a/src/main/java/org/prabuckt/application/vegancakes/model/Product.java b/src/main/java/org/prabuckt/application/vegancakes/model/Product.java
new file mode 100644
index 0000000..991377d
--- /dev/null
+++ b/src/main/java/org/prabuckt/application/vegancakes/model/Product.java
@@ -0,0 +1,156 @@
+package org.prabuckt.application.vegancakes.model;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+@Entity
+@Cacheable
+@NamedQueries({
+ // TODO fetch doesn't work with GlassFish
+ // @NamedQuery(name = Product.FIND_BY_CATEGORY_NAME, query =
+ // "SELECT p FROM Product p LEFT JOIN FETCH p.items LEFT JOIN FETCH p.category WHERE p.category.name =
+ // :pname"),
+ @NamedQuery(name = Product.FIND_BY_CATEGORY_NAME, query = "SELECT p FROM Product p WHERE p.category.name = :pname"),
+ @NamedQuery(name = Product.FIND_ALL, query = "SELECT p FROM Product p")
+})
+@XmlRootElement
+public class Product implements Serializable
+{
+
+ // ======================================
+ // = Attributes =
+ // ======================================
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(name = "id", updatable = false, nullable = false)
+ private Long id;
+ @Version
+ @Column(name = "version")
+ private int version;
+
+ @Column(length = 30, nullable = false)
+ @NotNull
+ @Size(min = 1, max = 30)
+ private String name;
+
+ @Column(length = 3000, nullable = false)
+ @NotNull
+ @Size(max = 3000)
+ private String description;
+
+ @ManyToOne(cascade = CascadeType.PERSIST)
+ @JoinColumn(name = "category_fk", nullable = false)
+ @XmlTransient
+ private Category category;
+
+ // ======================================
+ // = Constants =
+ // ======================================
+
+ public static final String FIND_BY_CATEGORY_NAME = "Product.findByCategoryName";
+ public static final String FIND_ALL = "Product.findAll";
+
+ // ======================================
+ // = Constructors =
+ // ======================================
+
+ public Product()
+ {
+ }
+
+ public Product(String name, String description, Category category)
+ {
+ this.name = name;
+ this.description = description;
+ this.category = category;
+ }
+
+ // ======================================
+ // = Getters & setters =
+ // ======================================
+
+ public Long getId()
+ {
+ return this.id;
+ }
+
+ public void setId(final Long id)
+ {
+ this.id = id;
+ }
+
+ public int getVersion()
+ {
+ return this.version;
+ }
+
+ public void setVersion(final int version)
+ {
+ this.version = version;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getDescription()
+ {
+ return description;
+ }
+
+ public void setDescription(String description)
+ {
+ this.description = description;
+ }
+
+ public Category getCategory()
+ {
+ return this.category;
+ }
+
+ public void setCategory(final Category category)
+ {
+ this.category = category;
+ }
+
+ // ======================================
+ // = Methods hash, equals, toString =
+ // ======================================
+
+ @Override
+ public final boolean equals(Object o)
+ {
+ if (this == o)
+ return true;
+ if (!(o instanceof Product))
+ return false;
+ Product product = (Product) o;
+ return Objects.equals(name, product.name) &&
+ Objects.equals(description, product.description);
+ }
+
+ @Override
+ public final int hashCode()
+ {
+ return Objects.hash(name, description);
+ }
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+}
diff --git a/src/main/java/org/prabuckt/application/vegancakes/model/PurchaseOrder.java b/src/main/java/org/prabuckt/application/vegancakes/model/PurchaseOrder.java
new file mode 100644
index 0000000..fa92ebe
--- /dev/null
+++ b/src/main/java/org/prabuckt/application/vegancakes/model/PurchaseOrder.java
@@ -0,0 +1,293 @@
+package org.prabuckt.application.vegancakes.model;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+import javax.persistence.*;
+import javax.validation.Valid;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@Entity
+@Table(name = "purchase_order")
+@XmlRootElement
+@NamedQueries({
+ @NamedQuery(name = PurchaseOrder.FIND_ALL, query = "SELECT o FROM PurchaseOrder o")
+})
+public class PurchaseOrder implements Serializable
+{
+
+ // ======================================
+ // = Attributes =
+ // ======================================
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(name = "id", updatable = false, nullable = false)
+ private Long id;
+ @Version
+ @Column(name = "version")
+ private int version;
+
+ @Column(name = "order_date", updatable = false)
+ @Temporal(TemporalType.DATE)
+ private Date orderDate;
+
+ @Column
+ private Float totalWithoutVat;
+
+ @Column(name = "vat_rate")
+ private Float vatRate;
+
+ @Column
+ private Float vat;
+
+ @Column
+ private Float totalWithVat;
+
+ @Column(name = "discount_rate")
+ private Float discountRate;
+
+ @Column
+ private Float discount;
+
+ @Column
+ private Float total;
+
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "customer_fk", nullable = false)
+ private Customer customer;
+
+ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
+ @JoinTable(name = "t_order_order_line", joinColumns = { @JoinColumn(name = "order_fk") }, inverseJoinColumns = {
+ @JoinColumn(name = "order_line_fk") })
+ private Set
+
+
To replace this page edit 'src/main/webapp/error.xhtml', or
+ keep Forging!
+
#{i18n.orderConfirmed_msg1}
+ +#{i18n.orderConfirmed_msg2}
+ +