diff --git a/pom.xml b/pom.xml index a41f2fc..0145b6f 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 0.0.2 war - Sale Dock - v${version} + Sale Dock - v${project.version} 17 @@ -55,6 +55,12 @@ jersey-hk2 3.1.5 + + commons-codec + commons-codec + 1.16.0 + + diff --git a/src/main/java/io/hardingadonis/saledock/dao/ICategoryDAO.java b/src/main/java/io/hardingadonis/saledock/dao/ICategoryDAO.java new file mode 100644 index 0000000..7df4f1b --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/dao/ICategoryDAO.java @@ -0,0 +1,6 @@ +package io.hardingadonis.saledock.dao; + +import io.hardingadonis.saledock.model.*; + +public interface ICategoryDAO extends IDAO { +} \ No newline at end of file diff --git a/src/main/java/io/hardingadonis/saledock/dao/ICustomerDAO.java b/src/main/java/io/hardingadonis/saledock/dao/ICustomerDAO.java new file mode 100644 index 0000000..3152daa --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/dao/ICustomerDAO.java @@ -0,0 +1,6 @@ +package io.hardingadonis.saledock.dao; + +import io.hardingadonis.saledock.model.*; + +public interface ICustomerDAO extends IDAO { +} \ No newline at end of file diff --git a/src/main/java/io/hardingadonis/saledock/dao/IDAO.java b/src/main/java/io/hardingadonis/saledock/dao/IDAO.java new file mode 100644 index 0000000..e111955 --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/dao/IDAO.java @@ -0,0 +1,14 @@ +package io.hardingadonis.saledock.dao; + +import java.util.*; + +public interface IDAO { + + public void add(T obj); + + public Optional getByID(Integer ID); + + public List getAll(); + + void update(T obj); +} diff --git a/src/main/java/io/hardingadonis/saledock/dao/IEmployeeDAO.java b/src/main/java/io/hardingadonis/saledock/dao/IEmployeeDAO.java new file mode 100644 index 0000000..004a7e2 --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/dao/IEmployeeDAO.java @@ -0,0 +1,6 @@ +package io.hardingadonis.saledock.dao; + +import io.hardingadonis.saledock.model.*; + +public interface IEmployeeDAO extends IDAO { +} \ No newline at end of file diff --git a/src/main/java/io/hardingadonis/saledock/dao/IOrderDAO.java b/src/main/java/io/hardingadonis/saledock/dao/IOrderDAO.java new file mode 100644 index 0000000..6805134 --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/dao/IOrderDAO.java @@ -0,0 +1,7 @@ +package io.hardingadonis.saledock.dao; + +import io.hardingadonis.saledock.model.*; + +public interface IOrderDAO extends IDAO { + +} \ No newline at end of file diff --git a/src/main/java/io/hardingadonis/saledock/dao/IProductDAO.java b/src/main/java/io/hardingadonis/saledock/dao/IProductDAO.java new file mode 100644 index 0000000..a9bee51 --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/dao/IProductDAO.java @@ -0,0 +1,6 @@ +package io.hardingadonis.saledock.dao; + +import io.hardingadonis.saledock.model.*; + +public interface IProductDAO extends IDAO { +} \ No newline at end of file diff --git a/src/main/java/io/hardingadonis/saledock/dao/impl/CategoryDAOImpl.java b/src/main/java/io/hardingadonis/saledock/dao/impl/CategoryDAOImpl.java new file mode 100644 index 0000000..f66fdd9 --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/dao/impl/CategoryDAOImpl.java @@ -0,0 +1,48 @@ +package io.hardingadonis.saledock.dao.impl; + +import io.hardingadonis.saledock.dao.*; +import io.hardingadonis.saledock.model.*; +import io.hardingadonis.saledock.utils.*; +import java.util.*; +import org.hibernate.*; + +public class CategoryDAOImpl implements ICategoryDAO { + + private final SessionFactory sessionFactory; + + public CategoryDAOImpl() { + this.sessionFactory = HibernateUtil.getSessionFactory(); + } + + @Override + public void add(Category obj) { + try (Session session = sessionFactory.openSession()) { + session.beginTransaction(); + session.persist(obj); + session.getTransaction().commit(); + } + } + + @Override + public Optional getByID(Integer ID) { + try (Session session = sessionFactory.openSession()) { + return Optional.ofNullable(session.get(Category.class, ID)); + } + } + + @Override + public List getAll() { + try (Session session = sessionFactory.openSession()) { + return session.createQuery("FROM Category", Category.class).getResultList(); + } + } + + @Override + public void update(Category obj) { + try (Session session = sessionFactory.openSession()) { + session.beginTransaction(); + session.merge(obj); + session.getTransaction().commit(); + } + } +} diff --git a/src/main/java/io/hardingadonis/saledock/dao/impl/CustomerDAOImpl.java b/src/main/java/io/hardingadonis/saledock/dao/impl/CustomerDAOImpl.java new file mode 100644 index 0000000..ba08b69 --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/dao/impl/CustomerDAOImpl.java @@ -0,0 +1,48 @@ +package io.hardingadonis.saledock.dao.impl; + +import io.hardingadonis.saledock.dao.*; +import io.hardingadonis.saledock.model.*; +import io.hardingadonis.saledock.utils.*; +import java.util.*; +import org.hibernate.*; + +public class CustomerDAOImpl implements ICustomerDAO { + + private final SessionFactory sessionFactory; + + public CustomerDAOImpl() { + this.sessionFactory = HibernateUtil.getSessionFactory(); + } + + @Override + public void add(Customer obj) { + try (Session session = sessionFactory.openSession()) { + session.beginTransaction(); + session.persist(obj); + session.getTransaction().commit(); + } + } + + @Override + public Optional getByID(Integer ID) { + try (Session session = sessionFactory.openSession()) { + return Optional.ofNullable(session.get(Customer.class, ID)); + } + } + + @Override + public List getAll() { + try (Session session = sessionFactory.openSession()) { + return session.createQuery("FROM Customer", Customer.class).getResultList(); + } + } + + @Override + public void update(Customer obj) { + try (Session session = sessionFactory.openSession()) { + session.beginTransaction(); + session.merge(obj); + session.getTransaction().commit(); + } + } +} diff --git a/src/main/java/io/hardingadonis/saledock/dao/impl/EmployeeDAOImpl.java b/src/main/java/io/hardingadonis/saledock/dao/impl/EmployeeDAOImpl.java new file mode 100644 index 0000000..8694800 --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/dao/impl/EmployeeDAOImpl.java @@ -0,0 +1,48 @@ +package io.hardingadonis.saledock.dao.impl; + +import io.hardingadonis.saledock.dao.*; +import io.hardingadonis.saledock.model.*; +import io.hardingadonis.saledock.utils.*; +import java.util.*; +import org.hibernate.*; + +public class EmployeeDAOImpl implements IEmployeeDAO { + + private final SessionFactory sessionFactory; + + public EmployeeDAOImpl() { + this.sessionFactory = HibernateUtil.getSessionFactory(); + } + + @Override + public void add(Employee obj) { + try (Session session = sessionFactory.openSession()) { + session.beginTransaction(); + session.persist(obj); + session.getTransaction().commit(); + } + } + + @Override + public Optional getByID(Integer ID) { + try (Session session = sessionFactory.openSession()) { + return Optional.ofNullable(session.get(Employee.class, ID)); + } + } + + @Override + public List getAll() { + try (Session session = sessionFactory.openSession()) { + return session.createQuery("FROM Employee", Employee.class).getResultList(); + } + } + + @Override + public void update(Employee obj) { + try (Session session = sessionFactory.openSession()) { + session.beginTransaction(); + session.merge(obj); + session.getTransaction().commit(); + } + } +} diff --git a/src/main/java/io/hardingadonis/saledock/dao/impl/OrderDAOImpl.java b/src/main/java/io/hardingadonis/saledock/dao/impl/OrderDAOImpl.java new file mode 100644 index 0000000..a64b788 --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/dao/impl/OrderDAOImpl.java @@ -0,0 +1,48 @@ +package io.hardingadonis.saledock.dao.impl; + +import io.hardingadonis.saledock.dao.*; +import io.hardingadonis.saledock.model.*; +import io.hardingadonis.saledock.utils.*; +import java.util.*; +import org.hibernate.*; + +public class OrderDAOImpl implements IOrderDAO { + + private final SessionFactory sessionFactory; + + public OrderDAOImpl() { + this.sessionFactory = HibernateUtil.getSessionFactory(); + } + + @Override + public void add(Order obj) { + try (Session session = sessionFactory.openSession()) { + session.beginTransaction(); + session.persist(obj); + session.getTransaction().commit(); + } + } + + @Override + public Optional getByID(Integer ID) { + try (Session session = sessionFactory.openSession()) { + return Optional.ofNullable(session.get(Order.class, ID)); + } + } + + @Override + public List getAll() { + try (Session session = sessionFactory.openSession()) { + return session.createQuery("FROM Order", Order.class).getResultList(); + } + } + + @Override + public void update(Order obj) { + try (Session session = sessionFactory.openSession()) { + session.beginTransaction(); + session.merge(obj); + session.getTransaction().commit(); + } + } +} diff --git a/src/main/java/io/hardingadonis/saledock/dao/impl/ProductDAOImpl.java b/src/main/java/io/hardingadonis/saledock/dao/impl/ProductDAOImpl.java new file mode 100644 index 0000000..05b193d --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/dao/impl/ProductDAOImpl.java @@ -0,0 +1,48 @@ +package io.hardingadonis.saledock.dao.impl; + +import io.hardingadonis.saledock.dao.*; +import io.hardingadonis.saledock.model.*; +import io.hardingadonis.saledock.utils.*; +import java.util.*; +import org.hibernate.*; + +public class ProductDAOImpl implements IProductDAO { + + private final SessionFactory sessionFactory; + + public ProductDAOImpl() { + this.sessionFactory = HibernateUtil.getSessionFactory(); + } + + @Override + public void add(Product obj) { + try (Session session = sessionFactory.openSession()) { + session.beginTransaction(); + session.persist(obj); + session.getTransaction().commit(); + } + } + + @Override + public Optional getByID(Integer ID) { + try (Session session = sessionFactory.openSession()) { + return Optional.ofNullable(session.get(Product.class, ID)); + } + } + + @Override + public List getAll() { + try (Session session = sessionFactory.openSession()) { + return session.createQuery("FROM Product", Product.class).getResultList(); + } + } + + @Override + public void update(Product obj) { + try (Session session = sessionFactory.openSession()) { + session.beginTransaction(); + session.merge(obj); + session.getTransaction().commit(); + } + } +} diff --git a/src/main/java/io/hardingadonis/saledock/model/Category.java b/src/main/java/io/hardingadonis/saledock/model/Category.java new file mode 100644 index 0000000..d39f2ca --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/model/Category.java @@ -0,0 +1,32 @@ +package io.hardingadonis.saledock.model; + +import jakarta.persistence.*; +import java.time.*; +import lombok.*; + +@Entity(name = "Category") +@Table(name = "`category`") +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@EqualsAndHashCode +@ToString +public class Category { + + @Id + @Column(name = "`id`") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer ID; + + @Column(name = "`name`") + private String name; + + @Column(name = "`created_at`") + private LocalDateTime createdAt; + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(ZoneId.of("Asia/Ho_Chi_Minh")); + } +} diff --git a/src/main/java/io/hardingadonis/saledock/model/Customer.java b/src/main/java/io/hardingadonis/saledock/model/Customer.java new file mode 100644 index 0000000..779cd21 --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/model/Customer.java @@ -0,0 +1,49 @@ +package io.hardingadonis.saledock.model; + +import jakarta.persistence.*; +import java.time.*; +import lombok.*; + +@Entity(name = "Customer") +@Table(name = "`customer`") +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@EqualsAndHashCode +@ToString +public class Customer { + + @Id + @Column(name = "`id`") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer ID; + + @Column(name = "`code`", unique = true) + private String code; + + @Column(name = "`name`") + private String name; + + @Column(name = "`email`", unique = true) + private String email; + + @Column(name = "`address`") + private String address; + + @Column(name = "`created_at`") + private LocalDateTime createdAt; + + @Column(name = "`updated_at`") + private LocalDateTime updatedAt; + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(ZoneId.of("Asia/Ho_Chi_Minh")); + } + + @PreUpdate + protected void onUpdate() { + this.updatedAt = LocalDateTime.now(ZoneId.of("Asia/Ho_Chi_Minh")); + } +} \ No newline at end of file diff --git a/src/main/java/io/hardingadonis/saledock/model/Employee.java b/src/main/java/io/hardingadonis/saledock/model/Employee.java new file mode 100644 index 0000000..dbdd99a --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/model/Employee.java @@ -0,0 +1,46 @@ +package io.hardingadonis.saledock.model; + +import jakarta.persistence.*; +import java.time.*; +import lombok.*; + +@Entity(name = "Employee") +@Table(name = "`employee`") +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@EqualsAndHashCode +@ToString +public class Employee { + + @Id + @Column(name = "`id`") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer ID; + + @Column(name = "`code`", unique = true) + private String code; + + @Column(name = "`password`", nullable = false) + private String hashedPassword; + + @Column(name = "`name`", nullable = false) + private String fullName; + + @Column(name = "`created_at`") + private LocalDateTime createdAt; + + @Column(name = "`updated_at`") + private LocalDateTime updatedAt; + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(ZoneId.of("Asia/Ho_Chi_Minh")); + } + + @PreUpdate + protected void onUpdate() { + this.updatedAt = LocalDateTime.now(ZoneId.of("Asia/Ho_Chi_Minh")); + } +} diff --git a/src/main/java/io/hardingadonis/saledock/model/Model.java b/src/main/java/io/hardingadonis/saledock/model/Model.java deleted file mode 100644 index abec6d3..0000000 --- a/src/main/java/io/hardingadonis/saledock/model/Model.java +++ /dev/null @@ -1,3 +0,0 @@ -package io.hardingadonis.saledock.model; - -public class Model {} diff --git a/src/main/java/io/hardingadonis/saledock/model/Order.java b/src/main/java/io/hardingadonis/saledock/model/Order.java new file mode 100644 index 0000000..a6992e2 --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/model/Order.java @@ -0,0 +1,76 @@ +package io.hardingadonis.saledock.model; + +import jakarta.persistence.*; +import java.time.*; +import java.util.*; +import lombok.*; + +@Entity(name = "Order") +@Table(name = "`order`") +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@EqualsAndHashCode +@ToString +public class Order { + + public static enum Status { + PENDING, + SHIPPING, + DONE, + CANCELLED + } + + @Id + @Column(name = "`id`") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer ID; + + @Column(name = "`code`", unique = true) + private String code; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "`employee_id`", nullable = false) + private Employee employee; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "`customer_id`", nullable = false) + private Customer customer; + + @Enumerated(EnumType.STRING) + @Column(name = "`status`", nullable = false) + private Status status; + + @Column(name = "`total`", nullable = false) + private Double total; + + @Column(name = "`note`", columnDefinition = "longtext") + private String note; + + @Column(name = "`created_at`") + private LocalDateTime createdAt; + + @Column(name = "`updated_at`") + private LocalDateTime updatedAt; + + @OneToMany(mappedBy = "order", fetch = FetchType.LAZY, cascade = CascadeType.ALL) + private List orderDetails = new ArrayList<>(); + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(ZoneId.of("Asia/Ho_Chi_Minh")); + } + + @PreUpdate + protected void onUpdate() { + this.updatedAt = LocalDateTime.now(ZoneId.of("Asia/Ho_Chi_Minh")); + } + + public void addProduct(Product product, Integer quantity) { + var detail = new OrderDetail(this, product); + detail.setQuantity(quantity); + + this.orderDetails.add(detail); + } +} diff --git a/src/main/java/io/hardingadonis/saledock/model/OrderDetail.java b/src/main/java/io/hardingadonis/saledock/model/OrderDetail.java new file mode 100644 index 0000000..c11c8a4 --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/model/OrderDetail.java @@ -0,0 +1,52 @@ +package io.hardingadonis.saledock.model; + +import jakarta.persistence.*; +import java.io.*; +import lombok.*; + +@Entity(name = "OrderDetail") +@Table(name = "order_detail") +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@EqualsAndHashCode +@ToString(exclude = {"order"}) +public class OrderDetail { + + @Embeddable + @AllArgsConstructor + @NoArgsConstructor + @Getter + @Setter + @EqualsAndHashCode + @ToString + public static class ID implements Serializable { + + @Column(name = "`order_id`") + private Integer orderID; + + @Column(name = "`product_id`") + private Integer productID; + } + + @EmbeddedId + private ID ID; + + @ManyToOne(fetch = FetchType.LAZY) + @MapsId("orderID") + private Order order; + + @ManyToOne(fetch = FetchType.LAZY) + @MapsId("productID") + private Product product; + + @Column(name = "`quantity`", nullable = false) + private int quantity; + + public OrderDetail(Order order, Product product) { + this.order = order; + this.product = product; + this.ID = new ID(order.getID(), product.getID()); + } +} diff --git a/src/main/java/io/hardingadonis/saledock/model/Product.java b/src/main/java/io/hardingadonis/saledock/model/Product.java new file mode 100644 index 0000000..0fa397b --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/model/Product.java @@ -0,0 +1,64 @@ +package io.hardingadonis.saledock.model; + +import jakarta.persistence.*; +import java.time.*; +import lombok.*; + +@Entity(name = "Product") +@Table(name = "`product`") +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@EqualsAndHashCode +@ToString +public class Product { + + @Id + @Column(name = "`id`") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer ID; + + @Column(name = "`code`", unique = true) + private String code; + + @Column(name = "`name`", nullable = false) + private String name; + + @Column(name = "`description`", columnDefinition = "longtext") + private String description; + + @Column(name = "`price`", nullable = false) + private Double price; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "`category_id`", nullable = false) + private Category category; + + @Column(name = "`image_url`", columnDefinition = "longtext") + private String imageURLs; + + @Column(name = "`created_at`") + private LocalDateTime createdAt; + + @Column(name = "`updated_at`") + private LocalDateTime updatedAt; + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(ZoneId.of("Asia/Ho_Chi_Minh")); + + if (this.imageURLs == null || this.imageURLs.isBlank()) { + this.imageURLs = "[]"; + } + } + + @PreUpdate + protected void onUpdate() { + this.updatedAt = LocalDateTime.now(ZoneId.of("Asia/Ho_Chi_Minh")); + + if (this.imageURLs == null || this.imageURLs.isBlank()) { + this.imageURLs = "[]"; + } + } +} diff --git a/src/main/java/io/hardingadonis/saledock/utils/Hash.java b/src/main/java/io/hardingadonis/saledock/utils/Hash.java new file mode 100644 index 0000000..41101ed --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/utils/Hash.java @@ -0,0 +1,10 @@ +package io.hardingadonis.saledock.utils; + +import org.apache.commons.codec.digest.*; + +public class Hash { + + public static String MD5(String message) { + return DigestUtils.md5Hex(message); + } +} diff --git a/src/main/java/io/hardingadonis/saledock/utils/Singleton.java b/src/main/java/io/hardingadonis/saledock/utils/Singleton.java new file mode 100644 index 0000000..87931cb --- /dev/null +++ b/src/main/java/io/hardingadonis/saledock/utils/Singleton.java @@ -0,0 +1,29 @@ +package io.hardingadonis.saledock.utils; + +import io.hardingadonis.saledock.dao.*; +import io.hardingadonis.saledock.dao.impl.*; + +public class Singleton { + + public static ICategoryDAO categoryDAO; + + public static ICustomerDAO customerDAO; + + public static IEmployeeDAO employeeDAO; + + public static IOrderDAO orderDAO; + + public static IProductDAO productDAO; + + static { + categoryDAO = new CategoryDAOImpl(); + + customerDAO = new CustomerDAOImpl(); + + employeeDAO = new EmployeeDAOImpl(); + + orderDAO = new OrderDAOImpl(); + + productDAO = new ProductDAOImpl(); + } +} diff --git a/src/main/resources/hibernate.cfg.xml b/src/main/resources/hibernate.cfg.xml index a06d8ce..1f441f1 100644 --- a/src/main/resources/hibernate.cfg.xml +++ b/src/main/resources/hibernate.cfg.xml @@ -9,16 +9,25 @@ - org.hibernate.dialect.MySQL8Dialect + org.hibernate.dialect.MySQLDialect true + true + true update + true + - + + + + + + \ No newline at end of file