Product.java
package com.stocks.stockease.model;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Domain entity representing a Product in the inventory system.
*
* Persisted to the "product" table with auto-increment ID. Maintains quantity and price
* with automatic total value recalculation. All fields are required (nullable=false).
*
* @author Team StockEase
* @version 1.0
* @since 2025-01-01
*/
@Data
@Entity
@Table(name = "product")
@NoArgsConstructor
@AllArgsConstructor
public class Product {
/**
* Unique product identifier. Auto-generated by database (auto-increment).
* Used as primary key for database relationships and API lookups.
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* Product display name. Required, unique constraint enforced at database level.
* Used for user-facing displays and search operations.
*/
@Column(nullable = false)
private String name;
/**
* Current stock quantity (integer count of units).
* Cannot be null or negative. Auto-recalculates totalValue when changed.
*/
@Column(nullable = false)
private Integer quantity;
/**
* Unit price in currency (double precision).
* Cannot be null or negative. Auto-recalculates totalValue when changed.
*/
@Column(nullable = false)
private Double price;
/**
* Computed total stock value. Automatically calculated as (quantity * price).
* Updated via custom setters to ensure consistency. Never manually set.
* Used for financial reporting and inventory valuation.
*/
@Column(nullable = false)
private Double totalValue;
/**
* Updates product quantity and recalculates total stock value.
*
* Overrides Lombok's default setter to maintain data consistency.
* Automatically recalculates totalValue = quantity * price.
*
* @param quantity new quantity in stock (must be non-negative)
*/
public void setQuantity(Integer quantity) {
this.quantity = quantity;
// Automatically recalculate to keep totalValue consistent with quantity/price changes
updateTotalValue();
}
/**
* Updates product unit price and recalculates total stock value.
*
* Overrides Lombok's default setter to maintain data consistency.
* Automatically recalculates totalValue = quantity * price.
*
* @param price new unit price (must be positive)
*/
public void setPrice(Double price) {
this.price = price;
// Automatically recalculate to keep totalValue consistent with quantity/price changes
updateTotalValue();
}
/**
* Internal helper to compute total stock value.
*
* Formula: totalValue = quantity * price
* Handles null cases (e.g., during object construction) by returning 0.0.
* Called by setQuantity() and setPrice() to maintain consistency.
*/
private void updateTotalValue() {
// Prevent null arithmetic; use 0 if either quantity or price is null
this.totalValue = (this.quantity != null && this.price != null) ? this.quantity * this.price : 0.0;
}
/**
* Constructs product entity for creation (without auto-generated ID).
*
* Used for new product insertion. ID is omitted; database generates it via auto-increment.
* Automatically calculates totalValue from provided quantity and price.
*
* @param name product name (required)
* @param quantity stock quantity (required, non-negative)
* @param price unit price (required, positive)
*/
public Product(String name, Integer quantity, Double price) {
this.name = name;
this.quantity = quantity;
this.price = price;
// Pre-calculate totalValue during construction for consistency
this.totalValue = (quantity != null && price != null) ? quantity * price : 0.0;
}
}