SQL Database Design
CREATE TABLE storage_facilities (
wh_code VARCHAR(20) NOT NULL COMMENT 'Unique facility code',
wh_name VARCHAR(100) NOT NULL COMMENT 'Facility name',
wh_address VARCHAR(255) COMMENT 'Physical address',
max_capacity INT COMMENT 'Storage capacity (units)',
PRIMARY KEY (wh_code)
) COMMENT='Storage Facilities Table';
CREATE TABLE material_types (
mat_code VARCHAR(20) NOT NULL COMMENT 'Unique material code',
mat_name VARCHAR(100) NOT NULL COMMENT 'Material name',
mat_spec VARCHAR(50) COMMENT 'Specifications',
mat_material VARCHAR(50) COMMENT 'Material composition',
PRIMARY KEY (mat_code),
UNIQUE KEY uq_mat_identifier (mat_name, mat_spec, mat_material)
) COMMENT='Material Types Table';
CREATE TABLE inventory_records (
record_id VARCHAR(15) NOT NULL COMMENT 'Inventory record ID (YYYYMMDDXXXX)',
operation VARCHAR(10) NOT NULL COMMENT 'Operation type: IN or OUT',
qty DECIMAL(10, 2) NOT NULL COMMENT 'Quantity',
unit VARCHAR(20) NOT NULL COMMENT 'Unit of measure',
wh_code VARCHAR(20) NOT NULL COMMENT 'Storage facility code',
mat_code VARCHAR(20) NOT NULL COMMENT 'Material type code',
notes TEXT COMMENT 'Additional notes',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 'Operation timestamp',
PRIMARY KEY (record_id),
FOREIGN KEY (wh_code) REFERENCES storage_facilities(wh_code),
FOREIGN KEY (mat_code) REFERENCES material_types(mat_code)
) COMMENT='Inventory Records Table';
Java Core Classes
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DbConnector {
private static final String DB_URL = "jdbc:mysql://localhost:3306/inventory_db";
private static final String USER = "inventory_user";
private static final String PASSWORD = "secure_pass";
static {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println("Database driver not found: " + e.getMessage());
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(DB_URL, USER, PASSWORD);
}
}
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class StorageFacility {
private String whCode;
private String whName;
private String whAddress;
private int maxCapacity;
public StorageFacility(String whCode, String whName, String whAddress, int maxCapacity) {
this.whCode = whCode;
this.whName = whName;
this.whAddress = whAddress;
this.maxCapacity = maxCapacity;
}
// Getters and Setters
public String getWhCode() { return whCode; }
public void setWhCode(String whCode) { this.whCode = whCode; }
public String getWhName() { return whName; }
public void setWhName(String whName) { this.whName = whName; }
public String getWhAddress() { return whAddress; }
public void setWhAddress(String whAddress) { this.whAddress = whAddress; }
public int getMaxCapacity() { return maxCapacity; }
public void setMaxCapacity(int maxCapacity) { this.maxCapacity = maxCapacity; }
public static void addFacility(StorageFacility facility) {
String sql = "INSERT INTO storage_facilities (wh_code, wh_name, wh_address, max_capacity) VALUES (?, ?, ?, ?)";
try (Connection conn = DbConnector.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, facility.getWhCode());
pstmt.setString(2, facility.getWhName());
pstmt.setString(3, facility.getWhAddress());
pstmt.setInt(4, facility.getMaxCapacity());
pstmt.executeUpdate();
System.out.println("Storage facility added successfully.");
} catch (SQLException e) {
System.err.println("Error adding facility: " + e.getMessage());
}
}
public static boolean deleteFacility(String whCode) {
String checkSql = "SELECT COUNT(*) FROM inventory_records WHERE wh_code = ?";
String deleteSql = "DELETE FROM storage_facilities WHERE wh_code = ?";
try (Connection conn = DbConnector.getConnection();
PreparedStatement checkStmt = conn.prepareStatement(checkSql);
PreparedStatement deleteStmt = conn.prepareStatement(deleteSql)) {
checkStmt.setString(1, whCode);
ResultSet rs = checkStmt.executeQuery();
if (rs.next() && rs.getInt(1) > 0) {
System.out.println("Cannot delete facility with existing inventory.");
return false;
}
deleteStmt.setString(1, whCode);
int rowsAffected = deleteStmt.executeUpdate();
return rowsAffected > 0;
} catch (SQLException e) {
System.err.println("Error deleting facility: " + e.getMessage());
return false;
}
}
public static List<StorageFacility> getAllFacilities() {
List<StorageFacility> facilities = new ArrayList<>();
String sql = "SELECT * FROM storage_facilities";
try (Connection conn = DbConnector.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
facilities.add(new StorageFacility(
rs.getString("wh_code"),
rs.getString("wh_name"),
rs.getString("wh_address"),
rs.getInt("max_capacity")
));
}
} catch (SQLException e) {
System.err.println("Error retrieving facilities: " + e.getMessage());
}
return facilities;
}
}
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class MaterialType {
private String matCode;
private String matName;
private String matSpec;
private String matMaterial;
public MaterialType(String matCode, String matName, String matSpec, String matMaterial) {
this.matCode = matCode;
this.matName = matName;
this.matSpec = matSpec;
this.matMaterial = matMaterial;
}
// Getters and Setters
public String getMatCode() { return matCode; }
public void setMatCode(String matCode) { this.matCode = matCode; }
public String getMatName() { return matName; }
public void setMatName(String matName) { this.matName = matName; }
public String getMatSpec() { return matSpec; }
public void setMatSpec(String matSpec) { this.matSpec = matSpec; }
public String getMatMaterial() { return matMaterial; }
public void setMatMaterial(String matMaterial) { this.matMaterial = matMaterial; }
public static void addMaterialType(MaterialType type) {
String sql = "INSERT INTO material_types (mat_code, mat_name, mat_spec, mat_material) VALUES (?, ?, ?, ?)";
try (Connection conn = DbConnector.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, type.getMatCode());
pstmt.setString(2, type.getMatName());
pstmt.setString(3, type.getMatSpec());
pstmt.setString(4, type.getMatMaterial());
pstmt.executeUpdate();
System.out.println("Material type added successfully.");
} catch (SQLException e) {
System.err.println("Error adding material type: " + e.getMessage());
}
}
public static boolean deleteMaterialType(String matCode) {
String checkSql = "SELECT COUNT(*) FROM inventory_records WHERE mat_code = ?";
String deleteSql = "DELETE FROM material_types WHERE mat_code = ?";
try (Connection conn = DbConnector.getConnection();
PreparedStatement checkStmt = conn.prepareStatement(checkSql);
PreparedStatement deleteStmt = conn.prepareStatement(deleteSql)) {
checkStmt.setString(1, matCode);
ResultSet rs = checkStmt.executeQuery();
if (rs.next() && rs.getInt(1) > 0) {
System.out.println("Cannot delete material type with existing inventory records.");
return false;
}
deleteStmt.setString(1, matCode);
int rowsAffected = deleteStmt.executeUpdate();
return rowsAffected > 0;
} catch (SQLException e) {
System.err.println("Error deleting material type: " + e.getMessage());
return false;
}
}
}
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class InventoryRecord {
private String recordId;
private String matCode;
private String whCode;
private String operation;
private double qty;
private String unit;
private String notes;
public InventoryRecord(String recordId, String matCode, String whCode, String operation, double qty, String unit, String notes) {
this.recordId = recordId;
this.matCode = matCode;
this.whCode = whCode;
this.operation = operation;
this.qty = qty;
this.unit = unit;
this.notes = notes;
}
// Getters and Setters
public String getRecordId() { return recordId; }
public void setRecordId(String recordId) { this.recordId = recordId; }
public String getMatCode() { return matCode; }
public void setMatCode(String matCode) { this.matCode = matCode; }
public String getWhCode() { return whCode; }
public void setWhCode(String whCode) { this.whCode = whCode; }
public String getOperation() { return operation; }
public void setOperation(String operation) { this.operation = operation; }
public double getQty() { return qty; }
public void setQty(double qty) { this.qty = qty; }
public String getUnit() { return unit; }
public void setUnit(String unit) { this.unit = unit; }
public String getNotes() { return notes; }
public void setNotes(String notes) { this.notes = notes; }
private static String generateRecordId() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String datePart = sdf.format(new Date());
String sql = "SELECT MAX(CAST(SUBSTRING(record_id, 9) AS UNSIGNED)) FROM inventory_records WHERE record_id LIKE ?";
try (Connection conn = DbConnector.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, datePart + "%");
ResultSet rs = pstmt.executeQuery();
int seq = 0;
if (rs.next()) {
seq = rs.getInt(1);
}
return datePart + String.format("%04d", seq + 1);
} catch (SQLException e) {
System.err.println("Error generating record ID: " + e.getMessage());
return datePart + "0001";
}
}
public static boolean addInboundRecord(String matCode, String whCode, double qty, String unit, String notes) {
String recordId = generateRecordId();
String sql = "INSERT INTO inventory_records (record_id, mat_code, wh_code, operation, qty, unit, notes) VALUES (?, ?, ?, 'IN', ?, ?, ?)";
try (Connection conn = DbConnector.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, recordId);
pstmt.setString(2, matCode);
pstmt.setString(3, whCode);
pstmt.setDouble(4, qty);
pstmt.setString(5, unit);
pstmt.setString(6, notes);
pstmt.executeUpdate();
System.out.println("Inbound record added successfully.");
return true;
} catch (SQLException e) {
System.err.println("Error adding inbound record: " + e.getMessage());
return false;
}
}
public static boolean addOutboundRecord(String matCode, String whCode, double qty, String unit, String notes) {
String checkSql = "SELECT SUM(CASE WHEN operation = 'IN' THEN qty ELSE -qty END) as current_qty FROM inventory_records WHERE mat_code = ? AND wh_code = ?";
String sql = "INSERT INTO inventory_records (record_id, mat_code, wh_code, operation, qty, unit, notes) VALUES (?, ?, ?, 'OUT', ?, ?, ?)";
try (Connection conn = DbConnector.getConnection();
PreparedStatement checkStmt = conn.prepareStatement(checkSql);
PreparedStatement pstmt = conn.prepareStatement(sql)) {
checkStmt.setString(1, matCode);
checkStmt.setString(2, whCode);
ResultSet rs = checkStmt.executeQuery();
if (!rs.next() || rs.getDouble("current_qty") < qty) {
System.out.println("Insufficient quantity available.");
return false;
}
String recordId = generateRecordId();
pstmt.setString(1, recordId);
pstmt.setString(2, matCode);
pstmt.setString(3, whCode);
pstmt.setDouble(4, qty);
pstmt.setString(5, unit);
pstmt.setString(6, notes);
pstmt.executeUpdate();
System.out.println("Outbound record added successfully.");
return true;
} catch (SQLException e) {
System.err.println("Error adding outbound record: " + e.getMessage());
return false;
}
}
public static List<InventoryRecord> getRecordsByMaterial(String matCode) {
List<InventoryRecord> records = new ArrayList<>();
String sql = "SELECT * FROM inventory_records WHERE mat_code = ?";
try (Connection conn = DbConnector.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, matCode);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
records.add(new InventoryRecord(
rs.getString("record_id"),
rs.getString("mat_code"),
rs.getString("wh_code"),
rs.getString("operation"),
rs.getDouble("qty"),
rs.getString("unit"),
rs.getString("notes")
));
}
} catch (SQLException e) {
System.err.println("Error retrieving records: " + e.getMessage());
}
return records;
}
}
Web Interface
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Inventory Management System - Login</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f0f2f5; color: #333; line-height: 1.6; }
.container { max-width: 400px; margin: 100px auto; padding: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { text-align: center; margin-bottom: 24px; color: #2c3e50; }
.form-group { margin-bottom: 16px; }
label { display: block; margin-bottom: 6px; font-weight: 500; }
input, select { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; }
button { width: 100%; padding: 12px; background-color: #3498db; color: white; border: none; border-radius: 4px; font-size: 16px; cursor: pointer; transition: background 0.3s; }
button:hover { background-color: #2980b9; }
.error { color: #e74c3c; margin-top: 10px; text-align: center; }
</style>
</head>
<body>
<div class="container">
<h1>Inventory Management System</h1>
<form id="loginForm">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
</div>
<div class="form-group">
<label for="role">Role:</label>
<select id="role" name="role" required>
<option value="admin">Administrator</option>
<option value="warehouse">Warehouse Manager</option>
</select>
</div>
<button type="submit">Login</button>
</form>
<div id="errorMessage" class="error"></div>
</div>
<script>
document.getElementById('loginForm').addEventListener('submit', function(e) {
e.preventDefault();
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
const role = document.getElementById('role').value;
const errorDiv = document.getElementById('errorMessage');
if (username && password) {
errorDiv.textContent = '';
if (role === 'admin') {
window.location.href = 'admin-dashboard.html';
} else {
window.location.href = 'warehouse-dashboard.html';
}
} else {
errorDiv.textContent = 'Please enter both username and password.';
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Administrator Dashboard</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f0f2f5; color: #333; line-height: 1.6; }
.header { background-color: #2c3e50; color: white; padding: 16px; display: flex; justify-content: space-between; align-items: center; }
.header h1 { font-size: 20px; }
.header .user-info { font-size: 14px; }
.sidebar { width: 200px; background-color: #34495e; color: white; height: calc(100vh - 64px); padding: 20px 0; position: fixed; }
.sidebar ul { list-style: none; }
.sidebar li { padding: 12px 20px; cursor: pointer; transition: background 0.3s; }
.sidebar li:hover { background-color: #3d566e; }
.content { margin-left: 200px; padding: 20px; }
.section { margin-bottom: 30px; padding: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); }
h2 { margin-bottom: 16px; color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 8px; }
.form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
.form-group { margin-bottom: 16px; }
label { display: block; margin-bottom: 6px; font-weight: 500; }
input, select { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; }
button { padding: 10px 20px; background-color: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer; transition: background 0.3s; margin-right: 10px; }
button:hover { background-color: #2980b9; }
.delete-btn { background-color: #e74c3c; }
.delete-btn:hover { background-color: #c0392b; }
table { width: 100%; border-collapse: collapse; margin-top: 16px; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }
th { background-color: #f8f9fa; font-weight: 600; color: #2c3e50; }
tr:hover { background-color: #f8f9fa; }
</style>
</head>
<body>
<div class="header">
<h1>Administrator Dashboard</h1>
<div class="user-info">
Welcome, Admin
<a href="login.html" style="color: #e3f2fd; margin-left: 10px; text-decoration: none;">Logout</a>
</div>
</div>
<div class="sidebar">
<ul>
<li data-section="facilities">Storage Facilities</li>
<li data-section="materials">Material Types</li>
</ul>
</div>
<div class="content">
<div id="facilitiesSection" class="section active">
<h2>Storage Facilities Management</h2>
<form id="facilityForm" class="form-grid">
<div class="form-group">
<label for="facilityCode">Facility Code:</label>
<input type="text" id="facilityCode" name="facilityCode" required>
</div>
<div class="form-group">
<label for="facilityName">Facility Name:</label>
<input type="text" id="facilityName" name="facilityName" required>
</div>
<div class="form-group">
<label for="facilityAddress">Address:</label>
<input type="text" id="facilityAddress" name="facilityAddress" required>
</div>
<div class="form-group">
<label for="capacity">Capacity:</label>
<input type="number" id="capacity" name="capacity" min="1" required>
</div>
<div style="grid-column: 1 / -1;">
<button type="submit">Add Facility</button>
</div>
</form>
<h3>Existing Facilities</h3>
<table id="facilitiesTable">
<thead>
<tr>
<th>Code</th>
<th>Name</th>
<th>Address</th>
<th>Capacity</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>WH001</td>
<td>Main Warehouse</td>
<td>123 Industrial Park, City Center</td>
<td>10000</td>
<td><button class="delete-btn">Delete</button></td>
</tr>
</tbody>
</table>
</div>
<div id="materialsSection" class="section">
<h2>Material Types Management</h2>
<form id="materialForm" class="form-grid">
<div class="form-group">
<label for="materialCode">Material Code:</label>
<input type="text" id="materialCode" name="materialCode" required>
</div>
<div class="form-group">
<label for="materialName">Material Name:</label>
<input type="text" id="materialName" name="materialName" required>
</div>
<div class="form-group">
<label for="materialSpec">Specifications:</label>
<input type="text" id="materialSpec" name="materialSpec" required>
</div>
<div class="form-group">
<label for="materialMaterial">Material:</label>
<input type="text" id="materialMaterial" name="materialMaterial" required>
</div>
<div style="grid-column: 1 / -1;">
<button type="submit">Add Material Type</button>
</div>
</form>
<h3>Existing Material Types</h3>
<table id="materialsTable">
<thead>
<tr>
<th>Code</th>
<th>Name</th>
<th>Specifications</th>
<th>Material</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>MT001</td>
<td>Steel Pipe</td>
<td>DN50, 6m</td>
<td>Carbon Steel</td>
<td><button class="delete-btn">Delete</button></td>
</tr>
</tbody>
</table>
</div>
</div>
<script>
const sidebarItems = document.querySelectorAll('.sidebar li');
const sections = document.querySelectorAll('.section');
sidebarItems.forEach(item => {
item.addEventListener('click', function() {
const targetSection = this.dataset.section;
sections.forEach(section => {
section.classList.remove('active');
});
document.getElementById(targetSection + 'Section').classList.add('active');
});
});
document.getElementById('facilityForm').addEventListener('submit', function(e) {
e.preventDefault();
console.log('Facility form submitted');
});
document.getElementById('materialForm').addEventListener('submit', function(e) {
e.preventDefault();
console.log('Material form submitted');
});
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', function() {
if (confirm('Are you sure you want to delete this item?')) {
console.log('Delete clicked');
}
});
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Warehouse Manager Dashboard</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f0f2f5; color: #333; line-height: 1.6; }
.header { background-color: #2c3e50; color: white; padding: 16px; display: flex; justify-content: space-between; align-items: center; }
.header h1 { font-size: 20px; }
.header .user-info { font-size: 14px; }
.sidebar { width: 200px; background-color: #34495e; color: white; height: calc(100vh - 64px); padding: 20px 0; position: fixed; }
.sidebar ul { list-style: none; }
.sidebar li { padding: 12px 20px; cursor: pointer; transition: background 0.3s; }
.sidebar li:hover { background-color: #3d566e; }
.content { margin-left: 200px; padding: 20px; }
.section { margin-bottom: 30px; padding: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); }
h2 { margin-bottom: 16px; color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 8px; }
.form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
.form-group { margin-bottom: 16px; }
label { display: block; margin-bottom: 6px; font-weight: 500; }
input, select { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; }
button { padding: 10px 20px; background-color: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer; transition: background 0.3s; margin-right: 10px; }
button:hover { background-color: #2980b9; }
.danger-btn { background-color: #e74c3c; }
.danger-btn:hover { background-color: #c0392b; }
table { width: 100%; border-collapse: collapse; margin-top: 16px; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }
th { background-color: #f8f9fa; font-weight: 600; color: #2c3e50; }
tr:hover { background-color: #f8f9fa; }
.success-message { color: #27ae60; margin-top: 16px; font-weight: 500; }
.error-message { color: #e74c3c; margin-top: 16px; font-weight: 500; }
</style>
</head>
<body>
<div class="header">
<h1>Warehouse Manager Dashboard</h1>
<div class="user-info">
Welcome, Warehouse Manager
<a href="login.html" style="color: #e3f2fd; margin-left: 10px; text-decoration: none;">Logout</a>
</div>
</div>
<div class="sidebar">
<ul>
<li data-section="inbound">Inbound Operations</li>
<li data-section="outbound">Outbound Operations</li>
<li data-section="inventory">Inventory Status</li>
</ul>
</div>
<div class="content">
<div id="inboundSection" class="section active">
<h2>Inbound Material Registration</h2>
<form id="inboundForm" class="form-grid">
<div class="form-group">
<label for="inMatCode">Material Code:</label>
<select id="inMatCode" name="inMatCode" required>
<option value="MT001">MT001 - Steel Pipe</option>
<option value="MT002">MT002 - Plastic Sheets</option>
</select>
</div>
<div class="form-group">
<label for="inWhCode">Warehouse:</label>
<select id="inWhCode" name="inWhCode" required>
<option value="WH001">WH001 - Main Warehouse</option>
<option value="WH002">WH002 - Secondary Warehouse</option>
</select>
</div>
<div class="form-group">
<label for="inQuantity">Quantity:</label>
<input type="number" id="inQuantity" name="inQuantity" min="0.01" step="0.01" required>
</div>
<div class="form-group">
<label for="inUnit">Unit:</label>
<input type="text" id="inUnit" name="inUnit" value="pcs" required>
</div>
<div class="form-group" style="grid-column: 1 / -1;">
<label for="inNotes">Notes:</label>
<input type="text" id="inNotes" name="inNotes">
</div>
<div style="grid-column: 1 / -1;">
<button type="submit">Register Inbound</button>
</div>
</form>
<div id="inboundResult"></div>
</div>
<div id="outboundSection" class="section">
<h2>Outbound Material Registration</h2>
<form id="outboundForm" class="form-grid">
<div class="form-group">
<label for="outMatCode">Material Code:</label>
<select id="outMatCode" name="outMatCode" required>
<option value="MT001">MT001 - Steel Pipe</option>
<option value="MT002">MT002 - Plastic Sheets</option>
</select>
</div>
<div class="form-group">
<label for="outWhCode">Warehouse:</label>
<select id="outWhCode" name="outWhCode" required>
<option value="WH001">WH001 - Main Warehouse</option>
<option value="WH002">WH002 - Secondary Warehouse</option>
</select>
</div>
<div class="form-group">
<label for="outQuantity">Quantity:</label>
<input type="number" id="outQuantity" name="outQuantity" min="0.01" step="0.01" required>
</div>
<div class="form-group">
<label for="outUnit">Unit:</label>
<input type="text" id="outUnit" name="outUnit" value="pcs" required>
</div>
<div class="form-group" style="grid-column: 1 / -1;">
<label for="outNotes">Notes:</label>
<input type="text" id="outNotes" name="outNotes">
</div>
<div style="grid-column: 1 / -1;">
<button type="submit">Register Outbound</button>
</div>
</form>
<div id="outboundResult"></div>
</div>
<div id="inventorySection" class="section">
<h2>Inventory Query</h2>
<div class="form-grid">
<div class="form-group">
<label for="queryMatCode">Material Code:</label>
<input type="text" id="queryMatCode" name="queryMatCode" placeholder="Enter material code">
</div>
<div class="form-group">
<label for="queryWhCode">Warehouse:</label>
<select id="queryWhCode" name="queryWhCode">
<option value="">All Warehouses</option>
<option value="WH001">WH001 - Main Warehouse</option>
<option value="WH002">WH002 - Secondary Warehouse</option>
</select>
</div>
</div>
<button id="queryBtn">Query Inventory</button>
<div id="inventoryResult"></div>
</div>
</div>
<script>
const sidebarItems = document.querySelectorAll('.sidebar li');
const sections = document.querySelectorAll('.section');
sidebarItems.forEach(item => {
item.addEventListener('click', function() {
const targetSection = this.dataset.section;
sections.forEach(section => {
section.classList.remove('active');
});
document.getElementById(targetSection + 'Section').classList.add('active');
});
});
document.getElementById('inboundForm').addEventListener('submit', function(e) {
e.preventDefault();
const resultDiv = document.getElementById('inboundResult');
resultDiv.className = 'success-message';
resultDiv.textContent = 'Inbound operation completed successfully!';
});
document.getElementById('outboundForm').addEventListener('submit', function(e) {
e.preventDefault();
const quantity = parseFloat(document.getElementById('outQuantity').value);
const resultDiv = document.getElementById('outboundResult');
if (quantity > 50) {
resultDiv.className = 'error-message';
resultDiv.textContent = 'Insufficient stock available. Available: 50 pcs';
} else {
resultDiv.className = 'success-message';
resultDiv.textContent = 'Outbound operation completed successfully!';
}
});
document.getElementById('queryBtn').addEventListener('click', function() {
const matCode = document.getElementById('queryMatCode').value;
const whCode = document.getElementById('queryWhCode').value;
const resultDiv = document.getElementById('inventoryResult');
if (!matCode) {
resultDiv.className = 'error-message';
resultDiv.textContent = 'Please enter a material code to query.';
return;
}
const table = document.createElement('table');
table.innerHTML = `
<thead>
<tr>
<th>Material Code</th>
<th>Warehouse</th>
<th>Current Stock</th>
<th>Unit</th>
</tr>
</thead>
<tbody>
<tr>
<td>${matCode || 'MT001'}</td>
<td>${whCode || 'All Warehouses'}</td>
<td>45</td>
<td>pcs</td>
</tr>
</tbody>
`;
resultDiv.innerHTML = '';
resultDiv.appendChild(table);
});
</script>
</body>
</html>
System Features
- Storage Facility Management: Add, delete, and view storage facilities with capacity tracking
- Material Type Management: Create and manage material types with unique identifiers
- Inventory Operations: Record inbound and outbound movements with quantity validation
- Inventory Tracking: Query current stock levels and view detailed movement history
- Role-Based Access: Separate dashboards for administrators and warehouse managers with appropriate permissions
- Transaction Logging: Automatically generate unique record IDs and timestamps for each inventory movement
Technical Stack
- Backend: Java with JDBC for database operations
- Database: MySQL with normalized schema design
- Frontend: HTML5, CSS3, and vanilla JavaScript for interactive UI
- Architecture: Three-tier architecture with clear separation between database, business logic, and presentation layers