Guide

Full Flux guide with the original sections, updated for the current Next.js + Flask + PostgreSQL architecture.

Flux Resell Tracker

Your operating manual for orders, parcels, inventory, sales, parser training, and admin recovery.

This guide keeps the structure of the original Flask page: a sticky contents nav, detailed member sections, and admin notes. The facts have been updated for the current stack: Next.js frontend pages, Flask-owned backend actions, PostgreSQL production, split IMAP ingest/parse queues, source-owned parser seeds, Product Matching, and approval-gated 90-day scans.

Frontend

Next.js renders migrated app pages; Flask pages remain for rollback and admin parity.

Backend

Flask, SQLAlchemy, workers, parsers, auth, and mutations stay canonical.

Email

IMAP ingest saves messages; parser workers process saved email IDs.

Getting Started

Flux tracks the path from buying stock to receiving parcels, adding inventory, logging sales, and reviewing profit. Discord remains the login and role gate. Flask owns auth, data, mutations, workers, and scheduled jobs; Next.js renders the member UI pages.

Start with Settings: connect eBay if you sell there, add IMAP email accounts for order and shipping emails, and configure Discord webhooks if you want alerts.
Use Orders for what you bought and Tracking for where parcels are. One Order can have many linked Shipments.
Inventory is opt-in. Email parsing never auto-creates inventory; promote an order only when it should become resale stock.
Production runs on PostgreSQL. The old Jinja pages remain available behind route rollback, but the live member pages are Next.js where migrated.

Dashboard

The Dashboard is the quick operating view. It keeps the same layout as the original page: timeframe controls, KPI cards, Operations Watch, Delivery Watch, Order Watch, charts, and breakdown cards.

Use 7D, 30D, 90D, or 1Y to change the reporting window.
Profit, revenue, items sold, and stock value come from inventory, sales, expenses, and synced eBay data.
Operations Watch shows awaiting shipment, in transit, delivered, and needs-attention counts from parsed orders and linked shipments.
Delivery Watch and Order Watch are shortcuts into the Tracking and Orders pages for current work.

Inventory

Inventory is your manually controlled stock list. It can be created manually, imported from CSV or Google Sheets, synced from eBay sales workflows, or created by promoting an order.

Add or edit item name, SKU, source, purchase price, quantity, status, image, notes, and purchase date.
Mark Sold creates a Sale record and updates stock status while preserving the inventory history.
CSV and Sheets imports include a mapping preview so weird column names can still land in the right fields.
Use export when you want a local backup or spreadsheet review.

Sales

Sales History records sold items, sale prices, fees, shipping costs, profit, platform, and dates. It feeds Dashboard and Analytics metrics.

Sales can be entered manually, imported from CSV or Sheets, or created by eBay sync.
The page shows revenue, profit, averages, recent activity, top performers, and a table/mobile layout.
Imports support column mapping and result messages, just like Inventory.
Clear All is destructive and should be used only after export or when resetting a dev/test account.

Order Tracking

Order and shipping tracking are split deliberately. Orders describe what was bought; Shipments describe parcel movement. This keeps split parcels and multiple carrier updates clean.

Orders are populated by order-confirmation parser definitions. Later invoices or confirmations enrich the same order without overwriting populated fields.
Shipments are linked to orders by order number or tracking number. Shipping emails are deferred if the parent order is not available yet.
Tracking Repair normalizes carrier aliases, merges short/full tracking duplicates, links repairable legacy rows, and removes unlinked orphan shipments.
The Delivery Calendar opens as a modal and shows delivered dates and ETA markers while keeping the main tracking table/card view in place.
Note: Normal email rescans are capped to 7 days. A 90-day retailer/parser rescan can be requested from Orders, but it waits for super-admin approval.

Analytics

Analytics is the deeper reporting view for trends, platform breakdowns, margin quality, and weekly comparison.

Date range controls update revenue, profit, fees, shipping, and margin calculations.
Charts show revenue/profit trend, platform mix, monthly summary, and top sellers.
Best and worst margins help identify pricing issues or sourcing wins.
Metrics remain user-scoped so one member cannot see another member data.

eBay Integration

eBay uses the REST Sell Fulfillment API with OAuth tokens stored encrypted by Flask. Next.js pages only start or display eBay actions; the backend owns token refresh and sync.

Connect eBay from Settings > eBay. The OAuth callback stays on Flask.
Manual sync queues backend work and imports orders/sales according to the existing eBay service logic.
Disconnect removes stored credentials for the current Flux account.
eBay sales are not used for Product Matching. Product Matching now learns only from parsed order rows and linked tracking context.

Email Sync (IMAP)

Email sync uses the newer split queue. IMAP ingest fetches and saves messages; email parse workers consume saved email IDs and run the data-driven parser engine.

IMAP IDLE listens on the configured primary mailbox and queues a one-hour scan only when new mail arrives.
Scheduled recovery runs every 15 minutes across smart folders with a one-hour lookback.
Daily/startup catch-up protects against outages with a bounded 7-day window.
Per-folder UID cursors prevent skipped messages when different folders have different UID sequences.
PostgreSQL allows safe scaling of parser workers with row locks; Flask workers still own all parsing and database writes.

Discord Notifications

Discord webhooks are configured from Settings and can alert on shipping, delivered, account issues, and system problems.

Use the default webhook URL for all categories or set per-category override URLs.
Send Test checks the active configuration without changing parser data.
Account issue alerts include IMAP login/sync problems and IDLE fallback warnings.
Webhook URLs are stored encrypted and are never exposed through Next state endpoints.

Importing Data

Flux supports CSV and Google Sheets imports for inventory and sales, plus email account import/export for operational setup.

CSV imports try common headers first, then show a mapping screen when a file needs help.
Sheets imports need a public sheet or an anyone-with-link URL.
Inventory imports can add stock; Sales imports can add completed sale history.
Email account exports do not expose stored passwords.

Tips & Tricks

A few habits keep Flux clean and fast while parser coverage grows.

When a parser is improved, use a normal 7-day order rescan first. Request 90 days only for a specific retailer/parser when you need older recovery.
If a retailer names the same product differently, use Admin > Product Matching to accept aliases into one main product title.
Keep unmatched emails as training evidence. They are often better than guessing from screenshots.
If a migrated Next page misbehaves in production, remove that nginx route and the old Flask/Jinja page returns without data changes.

FAQ

Common questions from the original guide, updated for the current architecture.

Why queue emails? Durable database queues make retries, task visibility, and PostgreSQL scale-out safe.
Why not Redis? PostgreSQL row-lock queueing is enough for this stage; Redis can wait until proven necessary.
Why not hardcoded parser classes? ParserDefinition and FieldMapping are editable in the admin workspace and easier to train from real samples.
Why no automatic inventory? Buying something does not always mean it should become resale stock.
Why Product Matching is admin-only? Accepted aliases are global and should apply consistently for every user.

Admin Guide

Admin pages are intentionally more conservative. Parser and control-centre workflows stay Flask-owned until each one has a proper parity pass.

Admin Panel

The Admin Console remains Flask/Jinja in this pass. It is the control centre for members, impersonation, Email Detection, maintenance mode, site updates, AI settings, and app configuration.

Use maintenance mode before risky production work. The splash page blocks normal login while maintenance is active, with admin access kept deliberately controlled.
Site Updates pulls from main and reloads the app from the server.
Impersonation is for support/debugging and should show a visible banner when active.
Admin Product Matching and Retailer Brands are Next pages because they are new admin workflows with typed APIs.

Parser Workspace

Parser Workspace is the admin tool for data-driven email extraction. Built-in seeds live in source-owned Python modules, but runtime parsing uses database definitions.

Import real .eml, HTML, or text samples into Email Detection and create or update ParserDefinition rows.
AI Suggest can propose regex/CSS mappings for required fields like order_id, item_name, quantity, price, tracking_number, carrier, and status.
Retailer-authored messages stay under retailer seed modules; logistics-authored messages stay under logistics seed modules.
Test mappings against samples before saving. The parser test panel shows missing required fields and extracted values.

Email Detection

Email Detection is the admin home for samples, parser definitions, unmatched emails, member submissions, and parser diagnostics.

Unmatched recent messages are kept for training so missed retailers can be recovered safely.
Save as sample lets you download/import examples without exposing private data broadly.
The reset controls are destructive and should be reserved for deliberate parser workspace cleanup.
Submitted samples from members help build new source-owned parser seeds like Nike, JB Hi-Fi, Kmart, Shippit, AusPost, and CouriersPlease.