← Back to Portfolio

Invoice Management System (IMS)

The Very Good Building & Development Company (VGB)

Role: Software Engineer (Java)
Timeline: 6 weeks (MVP)
Team: Solo project (course project)
Stack: Java • JDBC • MySQL • JUnit • CSV → DB migration • OOP
Focus: Pricing & tax rules engine, invoice generation, data integrity

Executive Summary

VGB managed invoices with spreadsheets and paper, leading to slow billing cycles and error-prone tax calculations. I built a robust Invoice Management System (IMS) that encodes business rules for equipment sales, leases, rentals, material sales, and subcontractor contracts. The system automates invoice creation, applies the correct tax logic per item type, and exports detailed and summary reports—always rounded to the nearest cent.

Problem

Solution

Business Rules Implemented

Equipment — Purchase

Subtotal = retail_price
Tax = 5.25% use tax of subtotal
Total = subtotal + tax

Equipment — Lease

Monthly base = retail_price / 60 (5 years)
Monthly with markup = 1.5 × base
Subtotal = months × monthly_with_markup
Lease-tax tier: small = untaxed, mid = $500 flat, large = $1,500 flat (thresholds configurable)

Equipment — Rental

Hourly rate = 0.1% of retail = 0.001 × retail_price
Subtotal = hours × hourly_rate
Tax = 4.38% sales tax of subtotal

Material Sale

Subtotal = unit_price × quantity (quantity must be an integer > 0)
Tax = 7.15% sales tax of subtotal

Contract (Subcontractor)

Subtotal = contract_amount
Tax = exempt

All money values rounded to nearest cent after each line-item computation.

Architecture (High Level)

UI[Invoice CLI / Report Export] --> SVC[Invoice Service]
SVC -->|reads/writes| DB[(MySQL)]
SVC --> RULES[Item Rules (OOP)]
RULES --> EP[EquipmentPurchase]
RULES --> EL[EquipmentLease]
RULES --> ER[EquipmentRental]
RULES --> MAT[Material]
RULES --> CON[Contract]

Data Model (Simplified)

COMPANY ||--o{ INVOICE : has INVOICE ||--|{ INVOICE_ITEM : contains ITEM ||--o{ INVOICE_ITEM : referenced COMPANY { uuid company_id PK string name } INVOICE { uuid invoice_id PK uuid company_id FK date invoice_date } ITEM { uuid item_uuid PK string item_type decimal retail_price decimal unit_price } INVOICE_ITEM { uuid invoice_item_id PK uuid invoice_id FK uuid item_uuid FK int quantity int hours int months decimal contract_amount }

Implementation Highlights

Encapsulation: LineItem (abstract) → subclasses compute subtotal(), tax(), total().

Precision: BigDecimal with setScale(2, RoundingMode.HALF_UP); no floating-point drift.

Validation: integer quantities for materials, non-negative hours/months, non-negative prices.

Configuration: tax rates & lease tiers externalized for future changes.

Testing: JUnit tests cover each rule + edge cases (zero quantities, tier boundaries).

Example (Java)

BigDecimal toCents(BigDecimal x) { return x.setScale(2, RoundingMode.HALF_UP); } class EquipmentRental extends LineItem { BigDecimal rate(BigDecimal retail) { // 0.1% of retail per hour return retail.multiply(new BigDecimal("0.001")); } public BigDecimal subtotal() { return toCents(rate(retailPrice).multiply(new BigDecimal(hours))); } public BigDecimal tax() { return toCents(subtotal().multiply(new BigDecimal("0.0438"))); } }

Results & Learnings

Automated invoice creation with deterministic rounding and rule enforcement.

Speed: CLI generates detailed + summary reports in seconds for multi-item invoices.

Quality: Unit tests prevent regressions when tax rates or tiers change.

Lesson: Keeping calculations inside each subclass made the code safer and easier to extend.

Next Steps

  • Web UI (Spring Boot + Thymeleaf/React) with CSV upload → DB.
  • Role-based access + audit logs.
  • Scheduled monthly reports and per-customer dashboards.