Skip to content

Latest commit

 

History

62 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

alt text

Now here's the reasoning behind every major decision:

- Why feature-based, not layer-based? A layer-based structure (models/, routes/, services/) means when you work on receipts, you're jumping between 4 folders. Feature-based means everything about receipts — model, schema, route, service, AI extractor — lives in features/receipts/. One folder, full context. This is how every serious production codebase is structured.

- Why ai_extractor.py inside the receipts feature? Because it's a receipt concern. If tomorrow we swap Anthropic for OpenAI, we change one file and nothing else breaks. service.py doesn't care how extraction works — it just calls extract_receipt_data(file_bytes) and gets structured JSON back. That's the boundary.

- Why shared/ on both sides? The rule is strict — features never import from each other. If expenses needs something from receipts, that thing belongs in shared/. This prevents the spaghetti that makes most codebases unmaintainable after 6 months.

- Why RTK Query on the frontend? It handles caching, loading/error states, and token refresh automatically. You'd spend a week building that from scratch with plain fetch. It pairs with Redux so your auth state (token, user) lives globally and any component can access it.

- Why docker-compose.yml at the root? One command — docker compose up — starts Postgres, the backend, and the frontend together. No "works on my machine" problems. This is also exactly what the CI/CD pipeline will use.


The receipt upload flow end to end:

1. User drops a file in UploadDropzone.jsx
2. receiptsApi.js sends a multipart/form-data POST to /receipts/upload
3. router.py validates the JWT, calls service.py
4. service.py uploads the raw file to GCS, then calls ai_extractor.py
5. ai_extractor.py sends the file + a structured extraction prompt to Anthropic API, gets back JSON (merchant, amount, date, category, line items)
6. service.py saves the receipt + creates an Expense record in Postgres
7. Response goes back to the frontend — the card re-renders with the extracted data


conda activate receipt-expense-assistant

And select the interpreter in VS Code as before (Ctrl+Shift+P → Python: Select Interpreter → pick receipt-assistant).
Future tip: if you ever add a new package to the project, just add it to environment.yml and run:

uvicorn app.main:app --reload

conda env update -f environment.yml --prune

login

{
  "email": "micah@test.com",
  "password": "password123"
}

alembic revision --autogenerate -m "create users table"

alembic revision --autogenerate -m "create receipts table"

alembic revision --autogenerate -m "add email verification to users"

alembic upgrade head

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages