LedgerFlow B2B accounting frontend — single-page app for POs, invoices, and EDI
Find a file
Adam Moussa c9821bfa85 Add invoice edit, delete, and bulk delete with confirmation UI
- Edit invoice modal reuses create form, pre-fills all fields including
  line items, locks invoice number and PO linkage
- Delete from detail view with confirmation dialog
- Multi-select checkboxes with bulk delete and confirmation modal listing
  all invoices to be removed
- Paid and EDI-submitted invoices cannot be selected for deletion
- "Modified After Send" orange badge for post-EDI-send edits
- PO remaining balance correctly accounts for current invoice during edit
- Edit button added to invoice table row actions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 11:41:56 -04:00
.gitignore Initial commit — LedgerFlow frontend 2026-04-02 18:19:49 -04:00
accounting-app.html Add invoice edit, delete, and bulk delete with confirmation UI 2026-04-03 11:41:56 -04:00
config.js Initial commit — LedgerFlow frontend 2026-04-02 18:19:49 -04:00
login.html Initial commit — LedgerFlow frontend 2026-04-02 18:19:49 -04:00
README.md Add invoice edit, delete, and bulk delete with confirmation UI 2026-04-03 11:41:56 -04:00
serve.js Initial commit — LedgerFlow frontend 2026-04-02 18:19:49 -04:00

LedgerFlow Frontend

Single-page web app for LedgerFlow — a B2B accounting tool for managing purchase orders, invoices, and EDI (X12 810) submissions to Amazon.

Deployed to S3 + CloudFront at https://ledgerflow.seahaven.com


Stack

  • Vanilla HTML/CSS/JS (no framework, no build step)
  • Google Identity Services for SSO
  • Calls the LedgerFlow backend API (Lambda + API Gateway)

Files

ledgerflow_frontend/
├── accounting-app.html    Main app (dashboard, POs, invoices, EDI, settings)
├── login.html             Google SSO login page
├── config.js              API URL + Google Client ID configuration
├── serve.js               Local dev server (Node.js)
├── .gitignore
└── README.md

Features

Purchase Orders

  • Import POs from external DynamoDB table (Coupa purchase-orders)
  • Add POs manually
  • Edit POs after import (vendor, amount, status, dates, notes)
  • Bill against POs to create invoices

Invoices

  • Create invoices linked to POs
  • Edit invoices (pre-filled modal with line items, totals recalculated in real-time)
  • Delete individual invoices from the detail view, or bulk-select and delete multiple at once
  • "Modified After Send" EDI status badge when an invoice is edited after EDI submission
  • Paid and EDI-submitted invoices are protected from selection/deletion
  • Line items with quantity, unit price, and descriptions
  • Payment terms: Net 15, Net 30, Net 45, Net 60, 90 NET, Due on Receipt
  • Due date auto-calculates based on selected payment terms
  • Tax rate from company settings
  • PO remaining balance updates in real-time during edit (accounts for current invoice)
  • Save as draft or queue for EDI submission

EDI (X12 810)

  • Preview generated X12 documents before submission
  • Submit invoices to AWS B2B Data Interchange
  • Transaction history and status tracking
  • ISA control number tracking

Settings / Connections

  • Company info (name, tax ID, invoice prefix, currency)
  • DynamoDB connection for external PO import
  • EDI configuration (sender/receiver IDs)
  • Connection status indicators in sidebar

Other

  • Google SSO with domain restriction
  • Sign out button in sidebar
  • Real-time dashboard with recent POs, invoices, and activity log

Local Development

node serve.js
# Opens at http://localhost:3000

The frontend calls the deployed AWS backend — there is no local backend server.


Deployment

The frontend is deployed automatically as part of cdk deploy in the backend repo. CDK's BucketDeployment syncs this directory to S3 and invalidates the CloudFront cache.

# From the backend repo:
cd infra
GOOGLE_CLIENT_ID=<your-client-id> npx cdk deploy --require-approval never

Configuration

Edit config.js to set:

window.LEDGERFLOW_API_URL = "https://your-api-gateway-url.amazonaws.com";
window.GOOGLE_CLIENT_ID   = "your-client-id.apps.googleusercontent.com";