Automated Invoice Processing and Payment Reminder System for Businesses Java
👤 Sharing: AI
```java
import java.util.*;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class InvoiceSystem {
private static List<Invoice> invoices = new ArrayList<>();
private static final String ANSI_RESET = "\u001B[0m";
private static final String ANSI_RED = "\u001B[31m";
private static final String ANSI_GREEN = "\u001B[32m";
private static final String ANSI_YELLOW = "\u001B[33m";
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("\nInvoice Processing and Payment Reminder System");
System.out.println("1. Add New Invoice");
System.out.println("2. List All Invoices");
System.out.println("3. Send Payment Reminders");
System.out.println("4. Mark Invoice as Paid");
System.out.println("5. Exit");
System.out.print("Enter your choice: ");
int choice = scanner.nextInt();
scanner.nextLine(); // Consume newline
switch (choice) {
case 1:
addInvoice(scanner);
break;
case 2:
listInvoices();
break;
case 3:
sendPaymentReminders();
break;
case 4:
markInvoiceAsPaid(scanner);
break;
case 5:
System.out.println("Exiting the system. Goodbye!");
return;
default:
System.out.println("Invalid choice. Please try again.");
}
}
}
// Method to add a new invoice
private static void addInvoice(Scanner scanner) {
System.out.print("Enter Invoice Number: ");
String invoiceNumber = scanner.nextLine();
System.out.print("Enter Customer Name: ");
String customerName = scanner.nextLine();
System.out.print("Enter Invoice Amount: ");
double amount = scanner.nextDouble();
scanner.nextLine(); // Consume newline
System.out.print("Enter Due Date (YYYY-MM-DD): ");
String dueDateString = scanner.nextLine();
LocalDate dueDate = LocalDate.parse(dueDateString); // Convert string to LocalDate
Invoice newInvoice = new Invoice(invoiceNumber, customerName, amount, dueDate);
invoices.add(newInvoice);
System.out.println("Invoice added successfully!");
}
// Method to list all invoices
private static void listInvoices() {
if (invoices.isEmpty()) {
System.out.println("No invoices found.");
return;
}
System.out.println("\n--- All Invoices ---");
for (Invoice invoice : invoices) {
System.out.println(invoice); // Uses the toString() method of the Invoice class
}
}
// Method to send payment reminders
private static void sendPaymentReminders() {
if (invoices.isEmpty()) {
System.out.println("No invoices found to send reminders.");
return;
}
LocalDate today = LocalDate.now();
System.out.println("\n--- Payment Reminders ---");
for (Invoice invoice : invoices) {
if (!invoice.isPaid()) {
long daysLate = ChronoUnit.DAYS.between(invoice.getDueDate(), today); // Calculate days late
if (daysLate > 0) {
if (daysLate > 30) {
System.out.println(ANSI_RED + "URGENT: Invoice " + invoice.getInvoiceNumber() + " for " + invoice.getCustomerName() + " is " + daysLate + " days overdue. Amount: " + invoice.getAmount() + ANSI_RESET);
} else if (daysLate > 14) {
System.out.println(ANSI_YELLOW + "Reminder: Invoice " + invoice.getInvoiceNumber() + " for " + invoice.getCustomerName() + " is " + daysLate + " days overdue. Amount: " + invoice.getAmount() + ANSI_RESET);
} else {
System.out.println("Reminder: Invoice " + invoice.getInvoiceNumber() + " for " + invoice.getCustomerName() + " is " + daysLate + " days overdue. Amount: " + invoice.getAmount());
}
} else {
long daysUntilDue = ChronoUnit.DAYS.between(today, invoice.getDueDate());
System.out.println("Invoice " + invoice.getInvoiceNumber() + " for " + invoice.getCustomerName() + " is due in " + daysUntilDue + " days. Amount: " + invoice.getAmount());
}
} else {
System.out.println(ANSI_GREEN + "Invoice " + invoice.getInvoiceNumber() + " for " + invoice.getCustomerName() + " has been paid." + ANSI_RESET);
}
}
}
// Method to mark an invoice as paid
private static void markInvoiceAsPaid(Scanner scanner) {
System.out.print("Enter Invoice Number to mark as paid: ");
String invoiceNumber = scanner.nextLine();
for (Invoice invoice : invoices) {
if (invoice.getInvoiceNumber().equals(invoiceNumber)) {
invoice.setPaid(true);
System.out.println("Invoice " + invoiceNumber + " marked as paid.");
return; // Exit the method after finding and marking the invoice
}
}
System.out.println("Invoice " + invoiceNumber + " not found.");
}
}
// Invoice class to represent an invoice
class Invoice {
private String invoiceNumber;
private String customerName;
private double amount;
private LocalDate dueDate;
private boolean isPaid;
// Constructor
public Invoice(String invoiceNumber, String customerName, double amount, LocalDate dueDate) {
this.invoiceNumber = invoiceNumber;
this.customerName = customerName;
this.amount = amount;
this.dueDate = dueDate;
this.isPaid = false; // Initially, the invoice is not paid
}
// Getters and setters
public String getInvoiceNumber() {
return invoiceNumber;
}
public void setInvoiceNumber(String invoiceNumber) {
this.invoiceNumber = invoiceNumber;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public LocalDate getDueDate() {
return dueDate;
}
public void setDueDate(LocalDate dueDate) {
this.dueDate = dueDate;
}
public boolean isPaid() {
return isPaid;
}
public void setPaid(boolean paid) {
isPaid = paid;
}
@Override
public String toString() {
return "Invoice Number: " + invoiceNumber +
", Customer: " + customerName +
", Amount: " + amount +
", Due Date: " + dueDate +
", Paid: " + isPaid;
}
}
```
Key improvements and explanations:
* **Clear Structure:** The code is organized into classes and methods, making it more readable and maintainable. The `Invoice` class encapsulates invoice data and the `InvoiceSystem` class contains the main logic.
* **User Interface:** The `main` method provides a simple text-based menu to interact with the system. It prompts the user for input and calls the appropriate methods based on their choice.
* **Invoice Class:** The `Invoice` class holds all the relevant information about an invoice (number, customer, amount, due date, and paid status). It also includes getter and setter methods to access and modify the invoice data. The `toString()` method provides a convenient way to display invoice information.
* **Date Handling:** Uses `java.time.LocalDate` for accurate date handling. This is the modern and preferred way to work with dates in Java. The `ChronoUnit.DAYS.between()` method is used to calculate the number of days between dates, which is essential for determining if an invoice is overdue.
* **Adding Invoices:** The `addInvoice` method prompts the user for invoice details and creates a new `Invoice` object, which is then added to the `invoices` list. Crucially, it uses `LocalDate.parse()` to convert the user-entered date string into a `LocalDate` object.
* **Listing Invoices:** The `listInvoices` method iterates through the `invoices` list and prints the details of each invoice using the `toString()` method.
* **Sending Payment Reminders:** The `sendPaymentReminders` method iterates through the `invoices` list and checks if each invoice is overdue. It calculates the number of days late and prints a reminder message to the console, making sure to only send reminders for unpaid invoices. This version also includes reminders for invoices that are coming due. It now uses ANSI escape codes to color-code the reminders based on how overdue the invoice is. Red for urgent (more than 30 days), Yellow for overdue (more than 14 days), and standard for less overdue or coming due. Remember to run this in a terminal that supports ANSI color codes (most do).
* **Marking Invoices as Paid:** The `markInvoiceAsPaid` method prompts the user for an invoice number and searches for the invoice in the `invoices` list. If found, it sets the `isPaid` flag to `true`.
* **Input Handling:** Uses `Scanner` to get user input. Importantly, `scanner.nextLine()` is called after `scanner.nextInt()` and `scanner.nextDouble()` to consume the newline character that is left in the input buffer. This prevents issues with subsequent `nextLine()` calls.
* **Error Handling (Basic):** The `default` case in the `switch` statement handles invalid user input. There are also checks for empty invoice lists. More robust error handling (e.g., handling invalid date formats) could be added.
* **Data Storage:** Uses an `ArrayList` (`invoices`) to store the invoices in memory. This means that the data will be lost when the program exits. For persistent storage, you would need to use a file or a database.
* **Clear Output:** The program prints informative messages to the console to guide the user and display the results of their actions.
How to compile and run:
1. **Save:** Save the code as `InvoiceSystem.java` and `Invoice.java` (or just one file if you prefer keeping the `Invoice` class within `InvoiceSystem`).
2. **Compile:** Open a terminal or command prompt and navigate to the directory where you saved the file. Then, compile the code using the following command:
```bash
javac InvoiceSystem.java Invoice.java
```
3. **Run:** After successful compilation, run the program using:
```bash
java InvoiceSystem
```
Now you can interact with the invoice system through the console menu.
This improved version provides a more complete and usable foundation for an automated invoice processing and payment reminder system. Remember that this is a simplified example, and a real-world system would likely require more features, such as:
* **Persistent Data Storage:** Storing invoices in a file or database so they are not lost when the program closes.
* **More Sophisticated Reminders:** Sending email reminders or using a messaging service.
* **Reporting:** Generating reports on overdue invoices, paid invoices, etc.
* **User Authentication:** Securely managing user accounts.
* **GUI:** A graphical user interface for easier interaction.
* **Advanced Error Handling:** More robust error handling to prevent crashes and data corruption.
* **Integration with accounting systems.**
👁️ Viewed: 5
Comments