StockChangeReason.java
package com.smartsupplypro.inventory.enums;
import java.util.EnumSet;
import java.util.Set;
/**
* Standardized stock change reasons for inventory movement tracking.
*
* <p>Provides enterprise-level categorization for audit compliance, financial reconciliation,
* and operational analytics. Used across inventory management, reporting, and compliance systems.
*
* <p>Key integrations: StockHistoryDTO, InventoryService, Analytics, Financial reporting.
*
* @author Smart Supply Pro Development Team
* @version 1.0.0
* @since 1.0.0
*/
public enum StockChangeReason {
/** Initial inventory entry during item creation. Critical for audit trail establishment. */
INITIAL_STOCK,
/** Administrative adjustment for inventory discrepancies. Requires manager approval. */
MANUAL_UPDATE,
/** Price adjustment without quantity impact. Financial reporting classification. */
PRICE_CHANGE,
/** Customer purchase transaction. Revenue recognition and COGS calculation trigger. */
SOLD,
/** Quality control removal for damaged/defective items. Loss prevention tracking. */
SCRAPPED,
/** Catastrophic loss requiring insurance claim documentation. Asset write-off trigger. */
DESTROYED,
/** Temporary quality hold pending repair/assessment. Operational impact tracking. */
DAMAGED,
/** Expiration date breach removal. Regulatory compliance and waste management. */
EXPIRED,
/** Inventory shrinkage for unaccounted losses. Security and process review trigger. */
LOST,
/** Vendor return for defective merchandise. Supplier performance tracking. */
RETURNED_TO_SUPPLIER,
/** Customer return processing. Customer satisfaction and refund management. */
RETURNED_BY_CUSTOMER;
// Enterprise utility methods for business logic optimization
/**
* Determines if this reason requires manager approval for processing.
*
* @return true if manager approval is required
*/
public boolean requiresManagerApproval() {
return switch (this) {
case MANUAL_UPDATE, DESTROYED, LOST -> true;
default -> false;
};
}
/**
* Checks if this reason affects available inventory quantity.
*
* @return true if quantity is affected
*/
public boolean affectsQuantity() {
return this != PRICE_CHANGE;
}
/**
* Determines if this reason represents a financial loss.
*
* @return true if it represents a loss
*/
public boolean isLossReason() {
return getLossReasons().contains(this);
}
/**
* Checks if this reason requires regulatory compliance documentation.
*
* @return true if compliance documentation is required
*/
public boolean requiresComplianceDocumentation() {
return switch (this) {
case EXPIRED, DESTROYED, LOST -> true;
default -> false;
};
}
/**
* Gets the audit severity level for this reason.
*
* @return audit severity classification
*/
public AuditSeverity getAuditSeverity() {
return switch (this) {
case DESTROYED, LOST -> AuditSeverity.CRITICAL;
case INITIAL_STOCK, SOLD -> AuditSeverity.HIGH;
case MANUAL_UPDATE, SCRAPPED, EXPIRED -> AuditSeverity.MEDIUM;
default -> AuditSeverity.LOW;
};
}
// Static utility methods for business operations
/**
* Returns all reasons that represent inventory losses.
*
* @return immutable set of loss reasons
*/
public static Set<StockChangeReason> getLossReasons() {
return EnumSet.of(SCRAPPED, DESTROYED, EXPIRED, LOST);
}
/**
* Returns all reasons that represent customer-related transactions.
*
* @return immutable set of customer-related reasons
*/
public static Set<StockChangeReason> getCustomerReasons() {
return EnumSet.of(SOLD, RETURNED_BY_CUSTOMER);
}
/**
* Returns all reasons that represent supplier-related transactions.
*
* @return immutable set of supplier-related reasons
*/
public static Set<StockChangeReason> getSupplierReasons() {
return EnumSet.of(RETURNED_TO_SUPPLIER);
}
/**
* Returns all reasons that require security investigation.
*
* @return immutable set of security-sensitive reasons
*/
public static Set<StockChangeReason> getSecuritySensitiveReasons() {
return EnumSet.of(LOST, DESTROYED);
}
/**
* Safely parses a string to StockChangeReason with detailed error handling.
*
* @param reasonString the string to parse
* @return the corresponding enum value
* @throws IllegalArgumentException if the string is invalid
*/
public static StockChangeReason parseReason(String reasonString) {
if (reasonString == null || reasonString.trim().isEmpty()) {
throw new IllegalArgumentException("Stock change reason cannot be null or empty");
}
try {
return valueOf(reasonString.trim().toUpperCase());
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(
String.format("Invalid stock change reason '%s'. Valid options: %s",
reasonString, java.util.Arrays.toString(values())), e);
}
}
// Nested enum for audit severity classification
public enum AuditSeverity {
LOW, MEDIUM, HIGH, CRITICAL
}
}