In this article, I’ll walk you through the process of developing a simple Invoice Management System using Java.
This project is perfect for beginners who want to strengthen their understanding of object-oriented programming (OOP) concepts like classes, objects, and collections while building something practical.
Table of Contents
Project Overview
The project consists of the following key functionalities:
- Add a customer
- Add an invoice
- Add items to an invoice
- List all customers
- List all invoices
- List all invoices of a customer
- Display the full details of an invoice
To implement this, we split the solution into three classes: Models.java, InvoiceService.java, and Main.java.
1. Defining the Models
Our first step is to define the core entities: Customer
, Item
, and Invoice
. These are the building blocks of our system.
Here’s the code for Models.java
:
import java.util.ArrayList;
import java.util.List;
class Customer {
String id;
String name;
Customer(String id, String name) {
this.id = id;
this.name = name;
}
}
class Item {
String name;
int quantity;
double price;
Item(String name, int quantity, double price) {
this.name = name;
this.quantity = quantity;
this.price = price;
}
}
class Invoice {
String id;
String customerId;
List<Item> items;
Invoice(String id, String customerId) {
this.id = id;
this.customerId = customerId;
this.items = new ArrayList<>();
}
double calculateTotal() {
double total = 0;
for (Item item : items) {
total += item.quantity * item.price;
}
return total;
}
}
Key Highlights:
Customer
andItem
are simple classes with fields for their respective attributes.Invoice
includes a list ofItem
objects, demonstrating how relationships between classes can be modeled.- The
calculateTotal
method inInvoice
iterates through the list of items and calculates the total cost.
2. Implementing the Invoice Service
The InvoiceService class contains the business logic for managing customers, invoices, and items. It uses HashMap
to store customers and invoices for quick lookups.
Here’s the code for InvoiceService.java
:
import java.util.HashMap;
import java.util.Map;
class InvoiceService {
private final Map<String, Customer> customers = new HashMap<>();
private final Map<String, Invoice> invoices = new HashMap<>();
public void addCustomer(String id, String name) {
customers.put(id, new Customer(id, name));
System.out.println("Customer added successfully.");
}
public void addInvoice(String id, String customerId) {
if (!customers.containsKey(customerId)) {
System.out.println("Customer not found!");
return;
}
invoices.put(id, new Invoice(id, customerId));
System.out.println("Invoice added successfully.");
}
public void addItemToInvoice(String invoiceId, String itemName, int quantity, double price) {
Invoice invoice = invoices.get(invoiceId);
if (invoice == null) {
System.out.println("Invoice not found!");
return;
}
invoice.items.add(new Item(itemName, quantity, price));
System.out.println("Item added successfully.");
}
public void listAllCustomers() {
if (customers.isEmpty()) {
System.out.println("No customers found.");
return;
}
System.out.println("--- Customers ---");
for (Customer customer : customers.values()) {
System.out.println("ID: " + customer.id + ", Name: " + customer.name);
}
}
public void listAllInvoices() {
if (invoices.isEmpty()) {
System.out.println("No invoices found.");
return;
}
System.out.println("--- Invoices ---");
for (Invoice invoice : invoices.values()) {
System.out.println("Invoice ID: " + invoice.id + ", Customer ID: " + invoice.customerId);
}
}
public void listInvoicesOfCustomer(String customerId) {
System.out.println("--- Invoices for Customer ID: " + customerId + " ---");
boolean found = false;
for (Invoice invoice : invoices.values()) {
if (invoice.customerId.equals(customerId)) {
System.out.println("Invoice ID: " + invoice.id);
found = true;
}
}
if (!found) {
System.out.println("No invoices found for this customer.");
}
}
public void displayInvoiceDetails(String invoiceId) {
Invoice invoice = invoices.get(invoiceId);
if (invoice == null) {
System.out.println("Invoice not found!");
return;
}
System.out.println("--- Invoice Details ---");
System.out.println("Invoice ID: " + invoice.id);
System.out.println("Customer ID: " + invoice.customerId);
System.out.println("Items:");
for (Item item : invoice.items) {
System.out.printf(" - %s: %d x %.2f = %.2f%n",
item.name, item.quantity, item.price, item.quantity * item.price);
}
System.out.printf("Total Amount: %.2f%n", invoice.calculateTotal());
}
}
Key Highlights:
- Validation checks ensure data consistency (e.g., verifying if a customer exists before adding an invoice).
- The
displayInvoiceDetails
method provides a detailed view of an invoice, including item-wise costs.
3. Building the Main Program
Finally, the Main.java
class provides a menu-driven interface to interact with the system.
Here’s the code for Main.java
:
import java.util.Scanner;
public class Main {
private static final Scanner scanner = new Scanner(System.in);
private static final InvoiceService service = new InvoiceService();
public static void main(String[] args) {
while (true) {
System.out.println("\n--- Invoice Management System ---");
System.out.println("1. Add a customer");
System.out.println("2. Add an invoice");
System.out.println("3. Add items to an invoice");
System.out.println("4. List all customers");
System.out.println("5. List all invoices");
System.out.println("6. List all invoices of a customer");
System.out.println("7. Display the full details of an invoice");
System.out.println("8. Exit");
System.out.print("Choose an option: ");
int choice = scanner.nextInt();
scanner.nextLine(); // Consume newline
switch (choice) {
case 1 -> addCustomer();
case 2 -> addInvoice();
case 3 -> addItemsToInvoice();
case 4 -> service.listAllCustomers();
case 5 -> service.listAllInvoices();
case 6 -> listInvoicesOfCustomer();
case 7 -> displayInvoiceDetails();
case 8 -> {
System.out.println("Exiting the system. Goodbye!");
return;
}
default -> System.out.println("Invalid choice. Please try again.");
}
}
}
private static void addCustomer() {
System.out.print("Enter customer ID: ");
String id = scanner.nextLine();
System.out.print("Enter customer name: ");
String name = scanner.nextLine();
service.addCustomer(id, name);
}
private static void addInvoice() {
System.out.print("Enter invoice ID: ");
String id = scanner.nextLine();
System.out.print("Enter customer ID: ");
String customerId = scanner.nextLine();
service.addInvoice(id, customerId);
}
private static void addItemsToInvoice() {
System.out.print("Enter invoice ID: ");
String invoiceId = scanner.nextLine();
System.out.print("Enter item name: ");
String itemName = scanner.nextLine();
System.out.print("Enter item quantity: ");
int quantity = scanner.nextInt();
System.out.print("Enter item price: ");
double price = scanner.nextDouble();
scanner.nextLine(); // Consume newline
service.addItemToInvoice(invoiceId, itemName, quantity, price);
}
private static void listInvoicesOfCustomer() {
System.out.print("Enter customer ID: ");
String customerId = scanner.nextLine();
service.listInvoicesOfCustomer(customerId);
}
private static void displayInvoiceDetails() {
System.out.print("Enter invoice ID: ");
String invoiceId = scanner.nextLine();
service.displayInvoiceDetails(invoiceId);
}
}
Conclusion
This project demonstrates how to build a simple yet functional invoice management system in Java.
It covers essential programming concepts like object-oriented design, data validation, and user interaction through a menu-driven interface.
Try extending this project by adding features like file persistence or a graphical user interface for more practice!