Invoice Generator

Apr 2026 - May 2026

Role: Fullstack Developer

Invoice Generator thumbnail
Tech Stack

Overview

Brill Invoicing is the internal invoicing module of the Brill Admin Dashboard, a custom-built admin panel developed for a HEPA air filter business. The Invoice Generator is the core feature — a fully interactive, multi-panel web form that allows the business to generate professional invoices for both dealers and retail customers. The system handles automatic shipping cost calculation via the Biteship API, dynamic item pricing per invoice type, a custom footer editor with live character counters, and a live PDF preview rendered through a hidden iframe. The project also delivers Brill Invoicing Lite, a standalone public-facing portfolio demo that showcases the full invoicing workflow without requiring a login or database connection.

In Collaboration With: Direct Client

Responsibilities

  • Designed the multi-panel form architecture: Invoice Meta, Items, Shipping, Discount & Fees, Footer Editor
  • Implemented custom PHP MVC-lite routing and controller structure
  • Invoice Meta: auto-generated invoice number, Jakarta-timezone date handling, Flatpickr due date with +3 day default
  • Invoice Type & Bill To: Dealer mode (searchable combobox from DB) and Customer mode (free text), with cascading downstream reset on type switch
  • Invoice Items: dynamic rows with preset catalog combobox and custom manual rows, real-time per-row amount calculation, duplicate item prevention, subtotal live preview
  • Shipping Fees: Manual free-text or Automatic via Biteship API with Area-Based (5-level address cascade) and Point-Based (Leaflet.js draggable map marker) delivery types
  • Courier and service selection rendering with price and ETA, auto-filling shipping cost on selection
  • Discount & Additional Fees: Flat and Percentage discount types with optional max cap, live grand total calculation
  • Footer Editor: live scaled preview, per-field character counters with 85% warning and 100% block, draft state tracking, revert-to-default per section
  • Invoice Preview via hidden iframe with postMessage handoff for log_id, Download PDF via browser print dialog
  • Invoice Log System: directory listing, re-render, update, and delete via dedicated API controllers
  • Brill Invoicing Lite: standalone CSV-backed address cascade (Banten province only), fixed IDR 10,000 shipping cost, no database, portable deployment
  • Mobile-responsive item table reworked into CSS Grid card layout with labeled pseudo-element columns
  • Combobox system rebuilt from scratch for Lite version (~500 lines vanilla JS, independent of main app)

Outcome

The Invoice Generator reduced invoice generation time from manual Word and Excel documents to under 2 minutes per invoice, with a consistent layout across all outputs. Dealer and retail customer invoice workflows were consolidated into a single UI. Real-time shipping cost lookup via the Biteship API eliminated manual courier rate checking. Every generated invoice is preserved in a log with re-render and re-download capability, giving the business a complete audit trail. The Brill Invoicing Lite demo was deployed as a public portfolio showcase accessible without credentials.

Detailed Breakdown

The section above is optimized for fast recruiter review. If you want the full implementation context, open the details below.

The business was generating invoices manually using Word or Excel documents, which led to inconsistent formatting, slow turnaround time, and no audit trail for past invoices. The process also required manual shipping rate lookups from third-party couriers, which was impractical when volume increased. Additionally, the portfolio version of the project needed to fully demonstrate the invoicing product without exposing proprietary business logic or requiring a login.

I designed and built a fully interactive Invoice Generator with a multi-panel web form. The system integrates the Biteship API for real-time shipping rate calculation, supports both area-based delivery (5-level address cascade from province to subdistrict) and coordinate-based delivery via a Leaflet.js map. Invoice output is rendered as a styled A4 HTML page using browser print for PDF generation without a server-side PDF library. Every generated invoice is persisted to a log table, enabling re-render, editing, and re-download. A standalone Lite version was built using CSV-backed address data and a fixed shipping cost, deployable on any PHP-capable host without a database or login.

Invoice Generator Flow

01

User opens /invoice-generator. Invoice number is auto-generated and invoice date defaults to today in Jakarta timezone (UTC+7). Due date defaults to +3 days via Flatpickr.

02

User selects Invoice Type: Dealer (searchable combobox fetches dealer list from database) or Customer (free-text input). Switching type cascades downstream — resets bill-to and recalculates item rates between reseller and retail pricing.

03

User builds item rows via preset catalog combobox (pricing changes based on invoice type) or custom manual rows. Each row calculates amount live (qty x rate). Subtotal updates in real-time. Valid item rows unlock the Shipping and Discount panels.

04

User configures shipping: Manual (free-text Ship To address) or Automatic via Biteship API. Automatic supports Area-Based delivery (Country to Province to City to District to Subdistrict, with postal code auto-fill on subdistrict selection) or Point-Based delivery (Leaflet.js map with draggable marker, synced to lat/lng text inputs).

05

Area or point selection triggers POST /api/shipping-quote to the Biteship API. Courier buttons render with logos. Selecting a courier filters its available services. Selecting a service auto-fills the shipping cost input.

06

User applies discount — Flat (direct IDR amount) or Percentage (with optional maximum IDR cap) — and an optional additional fee with label. Grand total = subtotal minus discount plus shipping plus additional fee, updated live.

07

User edits invoice footer: Notes section (header plus up to 3 paragraphs) and Closing section (header plus 1 paragraph). Each field has a character counter with 85% warning and 100% block. A live scaled preview reflects changes as the user types. Revert-to-default buttons restore company defaults per section.

08

User clicks Generate Invoice. Client-side validation runs, hidden fields are prepared, and the form POSTs to /invoice-generator/preview?nobar=1 inside a hidden iframe. The preview page renders a styled A4 invoice, saves it to log_invoice, and broadcasts an invoiceReady postMessage with the generated log_id back to the parent window.

09

Parent window captures log_id and enables the Download PDF button. Clicking it navigates to /invoice-log/preview?log_id=X&autodownload=1, which re-renders the invoice and triggers the browser print dialog for save-as-PDF.

Lite Demo Flow

01

User opens the standalone demo at /demos/brill-invoicing-lite. No login or database connection required.

02

Invoice type is locked to Customer Invoice. Bill To is free-text only. Up to 3 manual item rows can be added.

03

Shipping uses a CSV-backed PHP address endpoint limited to Banten province (Province to Regency to District to Subdistrict). Subdistrict selection auto-applies a fixed IDR 10,000 shipping cost. Instant delivery option is present but disabled, with a Bootstrap tooltip explaining the demo limitation.

04

Flat discount only. Footer editor is fully locked with lorem ipsum preview. All limited fields show an orange hint explaining the demo constraint. PDF download is intentionally disabled.

This project combined several non-trivial frontend and backend engineering decisions to deliver a seamless invoicing experience across both the full production system and the standalone demo version.

Key Technical Decisions

01

Jakarta timezone: custom jakartaDate() factory using manual UTC+7 offset calculation prevents client-timezone discrepancies for invoice and due dates.

02

Indonesian currency parsing: multi-pass heuristic handles periods as thousands separators and commas as decimal separators — opposite of most Western systems.

03

Combobox overflow escape: dropdown menus are detached from DOM on open, appended to document.body, and positioned via getBoundingClientRect(). A ResizeObserver and scroll listener keep the floating menu aligned while open.

04

Shipping re-query deduplication: an item-change signature (hash of item names and quantities) is stored and compared before each Biteship API call. A new quote is only requested when the signature changes, preventing redundant calls on blur events.

05

Invoice preview iframe height: after load, JavaScript reads contentDocument.body.scrollHeight and sets the iframe height explicitly, with a 960px minimum guard to prevent flash of undersized iframe.

06

PDF generation without a server-side library: the invoice is rendered as a styled A4 HTML page (1240x1754px) with @media print rules and triggered via window.print(), allowing the browser to save as PDF with exact layout fidelity.

07

Footer preview scaling: JavaScript measures the available container width, computes a scale ratio, and applies CSS transform: scale() to the preview canvas. The outer wrapper is sized in CSS units so layout flow is preserved.

08

Disabled Instant Delivery tooltip: the option uses a .is-disabled CSS class instead of the HTML disabled attribute so hover events still fire for Bootstrap tooltip initialization. The click handler checks for the class and blocks the action.

09

Lite combobox rebuilt from scratch: a plain object state map (addrCb) manages four address dropdowns with ~500 lines of vanilla JS, fully independent of the main app combobox system.

Implementation Details

  • PHP 7.4+ backend with strict types and custom MVC-lite routing (router.php to controller to model to JSON response)
  • MySQL/MariaDB via PDO for all data persistence in the production system
  • Tabler (Bootstrap 5) admin template for the UI framework
  • Flatpickr for date picking with minimum date constraint and default offset
  • Leaflet.js with OpenStreetMap tiles for the point-based delivery map interface
  • SweetAlert2 for confirmation dialogs
  • Biteship API integration via PHP cURL with stream_context fallback for SSL environments
  • Invoice generator JavaScript: single IIFE of approximately 1,925 lines organized into logical subsystems (meta, items, shipping, discount, footer, preview)
  • Invoice log persisted to log_invoice table with full CRUD: directory listing, re-render, update, delete
  • Lite version: CSV-backed PHP address endpoint, fixed shipping cost, no login required, no database dependency, portable shared hosting deployment

Explore More Projects

A few more top picks that show adjacent product, platform, and operations work across the portfolio.

View All Projects