expenseflow

module
v0.0.0-...-aec64cb Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 4, 2024 License: Apache-2.0

README ΒΆ

ExpenseFlow

Track and report professional expenses ExpenseFlow is an app designed to help professionals track and report their expenses. It simplifies the process of managing receipts, categorizing expenses, and generating reports, all from a single platform.

🚧 Features 🚧
  • Session-based expense tracking: Log expenses against a session (client or mission).
  • Expense details: Track the reason, value, date, and time of each expense.
  • Receipt capture: Upload photos of receipts.
  • Reports: Generate reports in a specific format.
  • Cross-platform support: Available on Android, iOS, Windows, Mac, Linux and Online.
Tech Stack
  • Backend: Go (Golang)
  • Frontend: Flutter
  • Database: SQLite
  • License: Apache 2.0
Roadmap
  1. Backend Development (Go)

    • Define data models (expenses, sessions, reasons, etc.)
    • Set up API routes for expense tracking:
      • POST /expenses: Add a new expense
      • GET /expenses: Get a list of all expenses
      • POST /receipts: Upload a receipt
      • GET /reports: Generate a report
    • Set up error handling, logging, and unit testing
    • Write documentation for the backend API (OpenAPI/Swagger)
  2. Frontend Development (Flutter)

    • Create basic UI for inputting expenses and sessions
    • Add functionality to upload receipt photos
    • Implement a report viewer
    • Handle authentication (connect to backend)
    • Perform user testing
  3. Deployment

    • Set up web hosting (use platforms like Firebase, DigitalOcean, etc.)
    • Prepare Android/iOS builds for Google Play and the Apple App Store
    • Ensure cross-platform compatibility for desktop versions
  4. Future Features

    • Push notifications for expense reminders
    • Multi-language support
    • Integration with other tools (e.g., Google Drive for backup)
    • Customizable filters/presentation for the report
    • Export in CSV/PDF/...
    • DB backup system
    • Show a lock design for sessions reported, warning when try to edit after report

Development Journal

First impressions

1. Roadmap Details
  • Data Models (Go):

    type Expense struct {
        ID         int
        SessionID  int
        Reason     string
        Value      float64
        DateTime   time.Time
        ReceiptURL string
    }
    
    type Session struct {
        ID      int
        Client  string
        Mission string
    }
    
  • API Design: Plan API endpoints. Need routes for adding expenses, uploading receipts, and generating reports.

  • Authentication: Can skip authentication early on, but eventually, want to handle user accounts. JWT (JSON Web Tokens) could be a good fit.

  • Testing: Write tests for the API routes as I go. Go has built-in testing functionality (go test).

2. Frontend Focus (Flutter)

Once the backend is functional, shift focus to Flutter. Keep it simple at first:

  • A form to add expenses
  • A file picker for receipt images
  • A report generator that formats data nicely

Tools

Install

Modify path in /config/config.go

Running:
go run ./cmd/expenseflow

### Dev
Use git hooks
```bash
git config core.hooksPath .githooks

### Testing:
```bash
go test ./tests

Change go test timeout in VS Code:

{
    "go.testTimeout": "10s"
}

Reminders

  • Handle overlap of a mission in reports from one week to another
  • Create INDEX for every FK
  • Create users(name, distance unit, date_display, week_start, language, standard_model, car_expense_rate_by_km)
  • Session start/end only need date not datetime
  • [front] Intercept the UNIQUE error of adding CarTrip.DateOnly and propose the user to add the new one to the existing one
  • [front] Check that Flutter handle the display of img with wrong extension but correct file header (if not, just add extension validation in back-end on top of header validation)
  • [front] Show sessions affected by the change of the value of an entity used as FK by another one. Example: session affected by the change of the name of a client.
  • Option to clear logs, limit size max

Important decisions

Choice of stack: Go / Flutter / SQLite:

Go is fast, simple and clear. After some courses on boot.dev I got attracted to it and wanted to make a full project to really compare to my other experiences in Python, my language of choice for many years, but also PHP, Java, TypeScript...

Flutter is my default choice in frontend. It's cross-platform most of all. I need more experience in it.

SQLite is also my default choice for database. Lightweight, it integrates well in mobile. ExpenseFlow doesn't have a huge amount of complex data to handle.

Codebase architecture
ExpenseFlow/
β”‚
β”œβ”€β”€ cmd/
β”‚   └── expenseflow/
β”‚       └── main.go         # Entry point of the application
β”‚
β”œβ”€β”€ internal/
β”‚   β”œβ”€β”€ db/
β”‚   β”‚   β”œβ”€β”€ models.go       # Database models (e.g., Expense, Session)
β”‚   β”‚   β”œβ”€β”€ queries.go      # Database query functions
β”‚   β”‚   └── init.go         # Database connection setup
β”‚   β”œβ”€β”€ handlers/
β”‚   β”‚   β”œβ”€β”€ expenses.go     # API route handlers (e.g., for adding expenses)
β”‚   β”‚   └── sessions.go     # API route handlers (e.g., for sessions)
β”‚   └── services/
β”‚       └── report.go       # Business logic (e.g., generating reports)
β”‚
β”œβ”€β”€ pkg/
β”‚   └── middleware/         # Any reusable middleware (e.g., authentication, logging)
β”‚
β”œβ”€β”€ api/
β”‚   └── routes.go           # Routes definition (e.g., registering API endpoints)
β”‚
β”œβ”€β”€ config/
β”‚   └── config.go           # Configuration (e.g., environment variables, app settings)
β”‚
β”œβ”€β”€ .gitignore
β”œβ”€β”€ go.mod
└── README.md
Date/Time

Everything will use the standard library "time" and will record UTC timestamps. Making the user able travel in different timezone and not confuse any logic. Flutter will be the one taking care of the preferred display for the user.

Receipt handling

I chose to have non-nullable in the DB. A placeholder IMG. So when I test Expense for validation it's not the same as when I CheckReceipt(). The latter will make sure the file exist and is not the placeholder. I think the user could add the picture later in their workflow when adding expense.

Hard limiting Float (for Amount.Value operations)

After creating some test to identify when Add or Sum were creating a float > math.MaxFloat64. I realized they were weird behaviors. You can't subtract a small float from a giant one, the result is unchanged. So I decided to hard code an unrealistic max in /config/config.go at 1_000_000_000.0

Datatype for IDs

sqlite3 drivers are returning int64 for ID columns. I decided to stick with int datatype in go (32 or 64 depending on the machine running.) It's very unlikely that I'll ever need int64, but I added a validation with Fatal if it ever occurs.

Logging

I will use the tag [info] for what's not fatal/error. I'll try to not crowd the logs with useless logic event. But for now any change to the DB is logged. And to avoid any security/privacy breach I'll only log IDs for information.

Problems and solutions

🚧

Design choices

🚧

Q/A to end users

  • Do I need a currency converter? Does the report show multiple totals depending on currency?
  • Multiple reports in case of multiple currencies.
  • What are the models/properties I'm missing?
  • Standard categories
  • Additional expense comment: Observation
  • Taxes by categories
  • Expenses can have Session = NULL
  • KM by session
  • opt VILLE > MISSION > opt VILLE

Directories ΒΆ

Path Synopsis
cmd
expenseflow command
internal
db

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL