Java Console Application for Warehouse Inventory Control
System Context
A manufacturing enterprise implementing digital transformation requires a supplementary Warehouse Management System (WMS) module for their existing ERP infrastructure. The solution must provide console-based tracking of inventory inbound/outbound operations, record modification capabilities, and real-time stock auditing through a menu-driven interface.
Data Structure Specification
Implement an InventoryRecord class encapsulating nine private attributes:
stockCode: String, 8-digit numeric product identifierproductName: String, descriptive item labelvendorName: String, supplier organization nameentryDate: String, 8-digit datestamp (YYYYMMDD) representing inbound timestampexitDate: String, 8-digit datestamp (YYYYMMDD) for outbound timestamp; empty if item remains in warehouse, otherwise must chronologically follow entryDatefacilityCode: String, 3-digit warehouse identifierbinCoordinates: String, 8-digit location signature formatted asAAAABBCCwhereAAAAdenotes rack number,BBindicates shelf level,CCrepresents position indexreceivedQty: int, total units receivedshippedQty: int, total units dispatched
Provide standard accessor (getter) and mutator (setter) methods for each field. Include a parameterized constructor accepting all nine attributes for object initialization.
Functional Requirements
1. Storage Architecture
Utilize an array structure capable of storing minimum five inventory records. Initialize the system with five sample records demonstrating valid data states.
2. Main Menu Interface
Render a hierarchical menu displaying four operational modes:
============================================================
Warehouse Management System v1.0
============================================================
1. Inbound Receipt Processing
2. Record Modification
3. Outbound Shipment Processing
4. Inventory Audit
============================================================
Accept numeric input 1-4 to navigate respective functions. Display error feedback for invalid selections and return to the main menu.
3. Inbound Receipt Processing
Input Sequence:
- Capture product code (validate 8-digit format)
- Capture product name
- Capture vendor information
- Capture entry date (validate 8-digit format)
- Capture facility code (validate 3-digit format)
- Capture bin coordinates (validate 8-digit format)
- Capture received quantity
Validation Logic: Enforce strict format validation at each step. Upon format violation, display "Input Error" and prompt for re-entry of the specific field.
Confirmation Workflow: After successful data capture, display complete record summary:
============================================================
Warehouse Management System v1.0
============================================================
Product Code: 20203982
Product Name: Huawei Notebook
Vendor: Hebei Zhengda Guangming Ltd.
Entry Date: 20230904
Facility: 003
Location: 01803501
Quantity: 100
============================================================
Commit transaction? (Y/N)
Selection Y persists data to the array and returns to main menu. Selection N discards inputs and returns to inbound entry screen.
4. Record Modification
Search Phase: Prompt for 8-digit product code. If no matching record exists, display "Item not found" and return to modification entry point.
Selection Phase: Display located record with enumerated fields (1-7):
============================================================
Warehouse Management System v1.0
============================================================
1. Product Code: 20203982
2. Product Name: Huawei Notebook
3. Vendor: Hebei Zhengda Guangming Ltd.
4. Entry Date: 20230904
5. Facility Code: 003
6. Location: 01803501
7. Quantity: 100
Select field to modify (1-7):
Validate selection range (1-7). Invalid selections trigger error messages and retturn to main menu.
Update Phase:
Capture new value for selected field. Present confirmation prompt: "Apply changes? (Y/N)". Selection Y commits mutation; N reverts to pre-edit values and returns to main menu.
5. Outbound Shipment Processing
Search Phase: Prompt for 8-digit product code. Handle missing records identically to modification workflow.
Shipment Capture: Display current inventory state including available balance (receivedQty - shippedQty). Prompt for:
- Exit date (8-digit validation)
- Shipment quantity (must be ≤ available balance)
Confirmation:
Present transaction summary with confirmation option. Persist updates to exitDate and shippedQty upon confirmation; otherwise return to outbound entry screen.
6. Inventory Audit
Generate comprehensive listing of all records displaying:
- Product Code
- Product Name
- Available Stock (calculated as receivedQty - shippedQty)
Format output as enumerated list with clear delimiters.
Implementation
File: InventoryRecord.java
public class InventoryRecord {
private String stockCode;
private String productName;
private String vendorName;
private String entryDate;
private String exitDate;
private String facilityCode;
private String binCoordinates;
private int receivedQty;
private int shippedQty;
public InventoryRecord(String stockCode, String productName, String vendorName,
String entryDate, String exitDate, String facilityCode,
String binCoordinates, int receivedQty, int shippedQty) {
this.stockCode = stockCode;
this.productName = productName;
this.vendorName = vendorName;
this.entryDate = entryDate;
this.exitDate = exitDate;
this.facilityCode = facilityCode;
this.binCoordinates = binCoordinates;
this.receivedQty = receivedQty;
this.shippedQty = shippedQty;
}
public String getStockCode() { return stockCode; }
public void setStockCode(String stockCode) { this.stockCode = stockCode; }
public String getProductName() { return productName; }
public void setProductName(String productName) { this.productName = productName; }
public String getVendorName() { return vendorName; }
public void setVendorName(String vendorName) { this.vendorName = vendorName; }
public String getEntryDate() { return entryDate; }
public void setEntryDate(String entryDate) { this.entryDate = entryDate; }
public String getExitDate() { return exitDate; }
public void setExitDate(String exitDate) { this.exitDate = exitDate; }
public String getFacilityCode() { return facilityCode; }
public void setFacilityCode(String facilityCode) { this.facilityCode = facilityCode; }
public String getBinCoordinates() { return binCoordinates; }
public void setBinCoordinates(String binCoordinates) { this.binCoordinates = binCoordinates; }
public int getReceivedQty() { return receivedQty; }
public void setReceivedQty(int receivedQty) { this.receivedQty = receivedQty; }
public int getShippedQty() { return shippedQty; }
public void setShippedQty(int shippedQty) { this.shippedQty = shippedQty; }
}
File: InventoryManager.java
import java.util.Scanner;
public class InventoryManager {
private InventoryRecord[] database;
private int activeRecords;
private Scanner input;
public InventoryManager() {
this.database = new InventoryRecord[50];
this.activeRecords = 0;
this.input = new Scanner(System.in);
initializeDataset();
}
private void initializeDataset() {
database[0] = new InventoryRecord("10000001", "Industrial Sensor", "TechCorp Industries", "20230115", "", "W01", "12340102", 500, 0);
database[1] = new InventoryRecord("10000002", "Hydraulic Pump", "FluidSystems Ltd.", "20230220", "20230310", "W02", "56780203", 200, 150);
database[2] = new InventoryRecord("10000003", "Control Valve", "ValveMasters Inc.", "20230305", "", "W01", "90120304", 350, 0);
database[3] = new InventoryRecord("10000004", "Circuit Breaker", "PowerSafe Co.", "20230412", "20230501", "W03", "34560405", 1000, 400);
database[4] = new InventoryRecord("10000005", "Pneumatic Cylinder", "AirMotion Tech", "20230518", "", "W02", "78900506", 250, 0);
activeRecords = 5;
}
public void displayMainMenu() {
System.out.println("============================================================");
System.out.println(" Warehouse Management System v1.0");
System.out.println("============================================================");
System.out.println(" 1. Inbound Receipt Processing");
System.out.println(" 2. Record Modification");
System.out.println(" 3. Outbound Shipment Processing");
System.out.println(" 4. Inventory Audit");
System.out.println("============================================================");
System.out.print("Select operation: ");
processMenuSelection();
}
private void processMenuSelection() {
String choice = input.nextLine().trim();
switch (choice) {
case "1": processInboundReceipt(); break;
case "2": processRecordModification(); break;
case "3": processOutboundShipment(); break;
case "4": generateAuditReport(); break;
default:
System.out.println("Invalid option. Please select 1-4.");
displayMainMenu();
}
}
private void processInboundReceipt() {
System.out.println("\n================ Inbound Receipt Processing ================");
String code = promptForValidatedInput("Product Code (8 digits): ", "^\\d{8}$", "Invalid format. Requires 8 digits.");
String name = promptForInput("Product Name: ");
String vendor = promptForInput("Vendor Name: ");
String entry = promptForValidatedInput("Entry Date (YYYYMMDD): ", "^\\d{8}$", "Invalid date format.");
String facility = promptForValidatedInput("Facility Code (3 digits): ", "^\\d{3}$", "Invalid format. Requires 3 digits.");
String location = promptForValidatedInput("Bin Location (8 digits, format AAAABBCC): ", "^\\d{8}$", "Invalid location format.");
int qty = Integer.parseInt(promptForValidatedInput("Received Quantity: ", "^\\d+$", "Invalid number."));
System.out.println("\n============================================================");
System.out.println("Product Code: " + code);
System.out.println("Product Name: " + name);
System.out.println("Vendor: " + vendor);
System.out.println("Entry Date: " + entry);
System.out.println("Facility: " + facility);
System.out.println("Location: " + location);
System.out.println("Quantity: " + qty);
System.out.println("============================================================");
System.out.print("Commit transaction? (Y/N): ");
if (input.nextLine().trim().equalsIgnoreCase("Y")) {
if (activeRecords < database.length) {
database[activeRecords] = new InventoryRecord(code, name, vendor, entry, "", facility, location, qty, 0);
activeRecords++;
System.out.println("Record committed successfully.");
} else {
System.out.println("Database capacity exceeded.");
}
} else {
System.out.println("Transaction cancelled.");
}
displayMainMenu();
}
private void processRecordModification() {
System.out.println("\n================== Record Modification ==================");
String searchCode = promptForInput("Enter 8-digit Product Code: ");
int index = findRecordIndex(searchCode);
if (index == -1) {
System.out.println("Item not found in database.");
processRecordModification();
return;
}
InventoryRecord rec = database[index];
System.out.println("\n1. Product Code: " + rec.getStockCode());
System.out.println("2. Product Name: " + rec.getProductName());
System.out.println("3. Vendor: " + rec.getVendorName());
System.out.println("4. Entry Date: " + rec.getEntryDate());
System.out.println("5. Facility Code: " + rec.getFacilityCode());
System.out.println("6. Bin Location: " + rec.getBinCoordinates());
System.out.println("7. Quantity: " + rec.getReceivedQty());
System.out.print("Select field to modify (1-7): ");
String field = input.nextLine().trim();
String originalValue = "";
switch (field) {
case "1":
originalValue = rec.getStockCode();
rec.setStockCode(promptForInput("Enter new Product Code: "));
break;
case "2":
originalValue = rec.getProductName();
rec.setProductName(promptForInput("Enter new Product Name: "));
break;
case "3":
originalValue = rec.getVendorName();
rec.setVendorName(promptForInput("Enter new Vendor: "));
break;
case "4":
originalValue = rec.getEntryDate();
rec.setEntryDate(promptForInput("Enter new Entry Date: "));
break;
case "5":
originalValue = rec.getFacilityCode();
rec.setFacilityCode(promptForInput("Enter new Facility Code: "));
break;
case "6":
originalValue = rec.getBinCoordinates();
rec.setBinCoordinates(promptForInput("Enter new Location: "));
break;
case "7":
originalValue = String.valueOf(rec.getReceivedQty());
rec.setReceivedQty(Integer.parseInt(promptForInput("Enter new Quantity: ")));
break;
default:
System.out.println("Invalid selection.");
displayMainMenu();
return;
}
System.out.print("Apply changes? (Y/N): ");
if (!input.nextLine().trim().equalsIgnoreCase("Y")) {
// Revert changes based on field
switch (field) {
case "1": rec.setStockCode(originalValue); break;
case "2": rec.setProductName(originalValue); break;
case "3": rec.setVendorName(originalValue); break;
case "4": rec.setEntryDate(originalValue); break;
case "5": rec.setFacilityCode(originalValue); break;
case "6": rec.setBinCoordinates(originalValue); break;
case "7": rec.setReceivedQty(Integer.parseInt(originalValue)); break;
}
System.out.println("Changes discarded.");
} else {
System.out.println("Record updated.");
}
displayMainMenu();
}
private void processOutboundShipment() {
System.out.println("\n=============== Outbound Shipment Processing ===============");
String searchCode = promptForInput("Enter 8-digit Product Code: ");
int index = findRecordIndex(searchCode);
if (index == -1) {
System.out.println("Item not found in database.");
processOutboundShipment();
return;
}
InventoryRecord rec = database[index];
int available = rec.getReceivedQty() - rec.getShippedQty();
System.out.println("Product: " + rec.getProductName());
System.out.println("Available Stock: " + available);
String exitDate = promptForValidatedInput("Exit Date (YYYYMMDD): ", "^\\d{8}$", "Invalid date format.");
int shipQty = Integer.parseInt(promptForValidatedInput("Shipment Quantity: ", "^\\d+$", "Invalid number."));
if (shipQty > available) {
System.out.println("Error: Shipment quantity exceeds available stock.");
processOutboundShipment();
return;
}
System.out.print("Confirm shipment? (Y/N): ");
if (input.nextLine().trim().equalsIgnoreCase("Y")) {
rec.setExitDate(exitDate);
rec.setShippedQty(rec.getShippedQty() + shipQty);
System.out.println("Shipment recorded.");
} else {
System.out.println("Operation cancelled.");
}
displayMainMenu();
}
private void generateAuditReport() {
System.out.println("\n==================== Inventory Audit ====================");
for (int i = 0; i < activeRecords; i++) {
InventoryRecord rec = database[i];
int balance = rec.getReceivedQty() - rec.getShippedQty();
System.out.printf("%d. Code: %s | Name: %s | Available: %d%n",
i + 1, rec.getStockCode(), rec.getProductName(), balance);
}
System.out.println("============================================================");
displayMainMenu();
}
private int findRecordIndex(String code) {
for (int i = 0; i < activeRecords; i++) {
if (database[i].getStockCode().equals(code)) return i;
}
return -1;
}
private String promptForInput(String message) {
System.out.print(message);
return input.nextLine().trim();
}
private String promptForValidatedInput(String message, String pattern, String errorMsg) {
while (true) {
System.out.print(message);
String value = input.nextLine().trim();
if (value.matches(pattern)) return value;
System.out.println("Error: " + errorMsg);
}
}
}
File: Application.java
public class Application {
public static void main(String[] args) {
InventoryManager manager = new InventoryManager();
manager.displayMainMenu();
}
}