Blame
|
1 | # Pocket Change Showdown: The Penny-Pincher's Paradise |
||||||
|
2 | |||||||
|
3 | > Fuck yeah! It's time to tackle your moving expenses with a dash of style and a whole lot of sass! π° |
||||||
|
4 | |||||||
| 5 | <div align="center"> |
|||||||
|
6 | |||||||
|
7 | Hey look, there's more Flair than a corporate drone with a Monday morning hangover! |
||||||
|
8 | |||||||
|
9 |  |
||||||
|
10 |  |
||||||
| 11 |  |
|||||||
|
12 |  |
||||||
|
13 | |||||||
|
14 | <img src="https://teb.codes/2-Code/Flask/Pocket-Change-Showdown/logo.png" alt="logo" width="150"/> |
||||||
|
15 | |||||||
|
16 | Think you're bad at managing expenses? Ah, quit your whining. We've got everything: [sassy Features](#features) β’ super-speed [Quick Start](#quick-start) β’ hassle-free [Installation](#installation) β’ wordy [Documentation](#documentation) β’ places to rant... I mean, [Contributing](#contributing)! |
||||||
|
17 | </div> |
||||||
| 18 | ||||||||
| 19 | --- |
|||||||
| 20 | ||||||||
| 21 | ## π Table of Contents |
|||||||
|
22 | - [What Features?](#features) |
||||||
| 23 | - [Screenshots β Because Who Reads?](#screenshots) |
|||||||
| 24 | - [Quick Start β No, Really, Itβs Quick](#quick-start) |
|||||||
| 25 | - [Slog through Installation](#installation) |
|||||||
| 26 | - [Docker - Walk the Weird Whale](#docker) |
|||||||
| 27 | - [Kubernetes - Because You're Fancy](#kubernetes) |
|||||||
| 28 | - [Local Mayhem - Developer Stuff](#local-development) |
|||||||
| 29 | - [Mess About with Configuration](#configuration) |
|||||||
| 30 | - [Usage - Whatβs the Point?](#usage) |
|||||||
| 31 | - [Guff About API Documentation](#api-documentation) |
|||||||
| 32 | - [What Matters in Development?](#development) |
|||||||
| 33 | - [License - Free Stuff's Always Good](#license) |
|||||||
|
34 | |||||||
| 35 | ## β¨ Features |
|||||||
| 36 | ### Core Functionality |
|||||||
|
37 | - πΈ **Receipt Management** - Store craploads of receipts. We dare you. |
||||||
| 38 | - π³ **Multiple Payment Methods** - We track whether you spent cash, credit, IOUs, or favors. |
|||||||
| 39 | - π·οΈ **Smart Categorization** - Keep your spending habits smart and snarky. |
|||||||
| 40 | - π **Analytics Dashboard** - Like looking at a magic crystal ball of shame. |
|||||||
| 41 | - π¨ **8 Color Themes** - Because your expenses can't be as drab as your personality. |
|||||||
| 42 | - π± **Mobile Responsive** - Track on the go, from your phone or hell, a potato. |
|||||||
| 43 | - π **No Login Required** - No strings attached, like that one-night stand. |
|||||||
|
44 | |||||||
| 45 | ### Data Management |
|||||||
|
46 | - π₯ **CSV Import** - Bring the madness of an Excel sheet to a whole new level. |
||||||
| 47 | - π€ **CSV Export** - Send your data on a field trip! |
|||||||
| 48 | - π **Template Download** - Look, Ma! Iβm organized. |
|||||||
| 49 | - πΎ **Persistent Storage** - Data that laughs in the face of restarts. |
|||||||
|
50 | |||||||
| 51 | ### PCS-Specific Categories |
|||||||
| 52 | - π Moving |
|||||||
| 53 | - βοΈ Travel |
|||||||
| 54 | - π Housing |
|||||||
| 55 | - π¦ Storage |
|||||||
| 56 | - π Transportation |
|||||||
| 57 | - π¨ Lodging |
|||||||
| 58 | - π Food |
|||||||
| 59 | - π¦ Supplies |
|||||||
| 60 | - ποΈ Services |
|||||||
|
61 | - β Make up your own crap! |
||||||
|
62 | |||||||
| 63 | ## πΈ Screenshots |
|||||||
| 64 | ||||||||
|
65 | <details> |
||||||
| 66 | <summary><i>Click to show screenshots</i></summary> |
|||||||
| 67 | # Dashboard |
|||||||
| 68 | Interactive analytics with spending trends and category breakdowns. |
|||||||
| 69 | ||||||||
| 70 | ||||||||
| 71 | # Expense Entry |
|||||||
| 72 | Simple form with receipt upload and auto-complete fields. |
|||||||
| 73 |  |
|||||||
| 74 | ||||||||
| 75 | # Homepage |
|||||||
| 76 | A general overview of expenses |
|||||||
| 77 |  |
|||||||
| 78 | ||||||||
| 79 | # Import/Export |
|||||||
| 80 | Efficient data importing and exporting with template |
|||||||
| 81 |  |
|||||||
| 82 | ||||||||
| 83 | # PDF Export |
|||||||
| 84 | Printer friendly PDF with customizable content |
|||||||
| 85 |  |
|||||||
| 86 | ||||||||
| 87 | # Settings |
|||||||
| 88 | Manage categories, payment methods, and themes. |
|||||||
| 89 |  |
|||||||
|
90 | |||||||
|
91 | </details> |
||||||
|
92 | |||||||
|
93 | ### Sample PDF |
||||||
|
94 | Donβt just stand there, gawk! [pdf_sample.pdf](./pdf_sample.pdf) |
||||||
|
95 | |||||||
|
96 | ## π Quick Start |
||||||
| 97 | ### Docker (Recommended) |
|||||||
| 98 | ```bash |
|||||||
|
99 | # Unleash the Kraken with the latest image |
||||||
|
100 | docker run -d \ |
||||||
| 101 | --name pcs-tracker \ |
|||||||
| 102 | -p 5001:5001 \ |
|||||||
| 103 | -v pcs-data:/app/data \ |
|||||||
| 104 | -v pcs-uploads:/app/uploads \ |
|||||||
| 105 | tebwritescode/pocket-change-showdown:latest |
|||||||
|
106 | # Chuckle maniacally at http://localhost:5001 |
||||||
|
107 | ``` |
||||||
| 108 | ||||||||
| 109 | ### Docker Compose |
|||||||
| 110 | ```bash |
|||||||
|
111 | # Phone-up Chuck Norris: "We're cloning a repo" |
||||||
|
112 | git clone https://github.com/tebwritescode/pocket-change-showdown.git |
||||||
| 113 | cd pocket-change-showdown |
|||||||
|
114 | # Compose your mess with Docker Compose |
||||||
|
115 | docker-compose up -d |
||||||
|
116 | # Dance your way to http://localhost:5001 |
||||||
|
117 | ``` |
||||||
| 118 | ||||||||
| 119 | ## π¦ Installation |
|||||||
| 120 | ### Docker |
|||||||
|
121 | #### Recognizing All Sorts |
||||||
| 122 | Because compatibility is key, unless it isn't! |
|||||||
|
123 | ```bash |
||||||
|
124 | # Pull for your peculiar machine |
||||||
|
125 | docker pull --platform linux/arm64 tebwritescode/pocket-change-showdown:latest |
||||||
|
126 | # Or let Docker rub its chin and decide |
||||||
|
127 | docker pull tebwritescode/pocket-change-showdown:latest |
||||||
| 128 | ``` |
|||||||
| 129 | ||||||||
|
130 | #### Docker Run Degeneracy |
||||||
|
131 | ```bash |
||||||
|
132 | # Deploy it, Captain |
||||||
|
133 | docker run -d \ |
||||||
| 134 | --name pcs-tracker \ |
|||||||
| 135 | -p 5001:5001 \ |
|||||||
| 136 | tebwritescode/pocket-change-showdown:latest |
|||||||
|
137 | # Make it last longer than a baking lesson |
||||||
|
138 | docker run -d \ |
||||||
| 139 | --name pcs-tracker \ |
|||||||
| 140 | -p 5001:5001 \ |
|||||||
| 141 | -v $(pwd)/data:/app/data \ |
|||||||
| 142 | -v $(pwd)/uploads:/app/uploads \ |
|||||||
| 143 | tebwritescode/pocket-change-showdown:latest |
|||||||
|
144 | # Secret sauce for the discerning chef |
||||||
|
145 | docker run -d \ |
||||||
| 146 | --name pcs-tracker \ |
|||||||
| 147 | -p 5001:5001 \ |
|||||||
| 148 | -e SECRET_KEY="your-secret-key-here" \ |
|||||||
| 149 | -e FLASK_ENV="production" \ |
|||||||
| 150 | -v pcs-data:/app/data \ |
|||||||
| 151 | -v pcs-uploads:/app/uploads \ |
|||||||
| 152 | tebwritescode/pocket-change-showdown:latest |
|||||||
| 153 | ``` |
|||||||
| 154 | ||||||||
| 155 | ### Kubernetes |
|||||||
| 156 | ```bash |
|||||||
|
157 | # Manifest your destiny, or just the code |
||||||
|
158 | kubectl apply -f k8s/ |
||||||
|
159 | # Or one by bloody one |
||||||
|
160 | kubectl apply -f k8s/namespace.yaml |
||||||
| 161 | kubectl apply -f k8s/secret.yaml |
|||||||
| 162 | kubectl apply -f k8s/pvc.yaml |
|||||||
| 163 | kubectl apply -f k8s/deployment.yaml |
|||||||
| 164 | kubectl apply -f k8s/service.yaml |
|||||||
|
165 | kubectl apply -f k8s/ingress.yaml # Optional, like an appendix |
||||||
|
166 | |||||||
|
167 | # Check if your stuff's intact |
||||||
|
168 | kubectl get all -n pcs-tracker |
||||||
|
169 | # If it worked, buy yourself a drink at http://<node-ip>:30001 |
||||||
|
170 | ``` |
||||||
| 171 | ||||||||
|
172 | #### Kubernetes Thingamabobs |
||||||
| 173 | - **Persistent Volumes** - Turns out you donβt need to webscrape for dataβit sticks around. |
|||||||
| 174 | - **Health Checks** - It only mostly dies. |
|||||||
| 175 | - **Resource Limits** - So demanding! |
|||||||
| 176 | - **Multi-Service** - Load balance like a tightrope walker. |
|||||||
| 177 | - **Ingress Ready** - Fancy domain? Me too. |
|||||||
|
178 | |||||||
| 179 | ### Local Development |
|||||||
| 180 | ```bash |
|||||||
|
181 | # Kiss the clouds goodbye |
||||||
|
182 | git clone https://github.com/tebwritescode/pocket-change-showdown.git |
||||||
| 183 | cd pocket-change-showdown |
|||||||
|
184 | # Create a virtual haven |
||||||
|
185 | python3 -m venv venv |
||||||
|
186 | source venv/bin/activate |
||||||
| 187 | # Unload a bag of dependencies |
|||||||
|
188 | pip install -r requirements.txt |
||||||
|
189 | # Go-Go-Gadget application |
||||||
|
190 | python app.py |
||||||
|
191 | # Channel your inner regulator at http://localhost:5001 |
||||||
|
192 | ``` |
||||||
| 193 | ||||||||
| 194 | ## βοΈ Configuration |
|||||||
| 195 | ### Environment Variables |
|||||||
| 196 | | Variable | Description | Default | |
|||||||
| 197 | |----------|-------------|---------| |
|||||||
|
198 | | `SECRET_KEY` | SMERSH-level deception sessions key | `pcs-secret-key-2024` | |
||||||
| 199 | | `FLASK_ENV` | Sneaky environment mood | `production` | |
|||||||
| 200 | | `DATABASE_URL` | Alchemize this: your database | `sqlite:///data/pcs_tracker.db` | |
|||||||
| 201 | | `MAX_CONTENT_LENGTH` | Maximum cr-p (content) upload size | `16777216` (16MB) | |
|||||||
|
202 | |||||||
| 203 | ### Data Persistence |
|||||||
|
204 | To make data hang around like a bad smell: |
||||||
| 205 | - `/app/data` - SQLite domicile |
|||||||
| 206 | - `/app/uploads` - Receipts chill as BLOBs |
|||||||
|
207 | |||||||
| 208 | ## π± Usage |
|||||||
|
209 | ### Tossin' Pennies - Adding Expenses |
||||||
| 210 | 1. Sing "Add Expense!" from any rooftop or just click it |
|||||||
| 211 | 2. Wake up from title-only dream |
|||||||
| 212 | 3. Attach facepalming receipts (optional) |
|||||||
| 213 | 4. Ceremoniously hit "Save" |
|||||||
| 214 | ||||||||
| 215 | ### Inflicting Data - Importing |
|||||||
| 216 | 1. Explore **Import/Export** β **Import CSV** |
|||||||
| 217 | 2. Don shiny template armor |
|||||||
| 218 | 3. Be daVinci, fill your masterpiece |
|||||||
| 219 | 4. Blast off with CSV sere-naah-de |
|||||||
| 220 | ||||||||
| 221 | ### Cheese-Cutting Format |
|||||||
|
222 | ```csv |
||||||
| 223 | Date,Title,Description,Category,Cost,Payment Method,Location,Vendor,Notes,Tags |
|||||||
| 224 | 2024-01-15,Moving Truck,U-Haul rental,Moving,299.99,Credit Card,Downtown,U-Haul,26ft truck,moving |
|||||||
| 225 | 2024-01-16,Hotel Stay,Overnight stay,Lodging,125.00,Company Card,Holiday Inn,Holiday Inn,1 night,travel |
|||||||
| 226 | ``` |
|||||||
| 227 | ||||||||
|
228 | ### Manipulating Categories & Payment Methods |
||||||
| 229 | 1. Go where no wo/man has deemed necessary: **Settings** |
|||||||
| 230 | 2. Cust-omize your little heart out |
|||||||
| 231 | 3. Create methods even mad scientists couldnβt |
|||||||
| 232 | 4. Marry whimsy: color themes purr with indulgence |
|||||||
|
233 | |||||||
|
234 | ### Accidental Analytics Dashboard |
||||||
| 235 | - Scorn last week, guilt-trip for next: from nanosecond to year |
|||||||
| 236 | - See-spend scenario via doughnut dive |
|||||||
| 237 | - Payment method squabbles (Bar chart showdown) |
|||||||
| 238 | - Dailies take you on the trend train (Line chart) |
|||||||
| 239 | - Top dog categories, percentages & flaunting aplenty |
|||||||
|
240 | |||||||
|
241 | ## π API Guff |
||||||
|
242 | ### Endpoints |
||||||
|
243 | | Method | Endpoint | Quirky Description | |
||||||
| 244 | |--------|----------|--------------------| |
|||||||
| 245 | | GET | `/` | Home sweet home(wrecker) | |
|||||||
| 246 | | GET | `/expenses` | Expense expedition | |
|||||||
| 247 | | GET/POST | `/expense/new` | New expense enlightenment | |
|||||||
| 248 | | GET/POST | `/expense/<id>/edit` | Edit the unavoidable | |
|||||||
| 249 | | POST | `/expense/<id>/delete` | PURGE! | |
|||||||
| 250 | | GET | `/expense/<id>/receipt` | Picture-perception | |
|||||||
| 251 | | GET | `/dashboard` | Analytical nincompoopery | |
|||||||
| 252 | | GET | `/api/expense_data` | JSON chateria | |
|||||||
| 253 | | GET/POST | `/settings` | Mischief management | |
|||||||
| 254 | | POST | `/settings/category/add` | Go rogue - add category | |
|||||||
| 255 | | POST | `/settings/payment/add` | Payment etiquette upgrade | |
|||||||
| 256 | | GET | `/export` | CSV in Wonderland | |
|||||||
| 257 | | GET/POST | `/import` | CSV Carousel | |
|||||||
| 258 | | GET | `/template` | CSV preface nobility | |
|||||||
| 259 | ||||||||
| 260 | ### API Response Satire |
|||||||
|
261 | ```json |
||||||
| 262 | GET /api/expense_data?period=month |
|||||||
| 263 | { |
|||||||
| 264 | "categories": { |
|||||||
| 265 | "labels": ["Moving", "Travel", "Housing"], |
|||||||
| 266 | "data": [1250.50, 890.25, 2100.00] |
|||||||
| 267 | }, |
|||||||
| 268 | "payment_methods": { |
|||||||
| 269 | "labels": ["Credit Card", "Cash", "Company Card"], |
|||||||
| 270 | "data": [3500.75, 450.00, 290.00] |
|||||||
| 271 | }, |
|||||||
| 272 | "daily_trend": { |
|||||||
| 273 | "labels": ["2024-01-01", "2024-01-02"], |
|||||||
| 274 | "data": [125.50, 340.25] |
|||||||
| 275 | } |
|||||||
| 276 | } |
|||||||
| 277 | ``` |
|||||||
| 278 | ||||||||
|
279 | ## π οΈ Development - Why Bother? |
||||||
|
280 | ### Tech Stack |
||||||
|
281 | - **Backend**: Flask, spicy SQLAlchemy |
||||||
| 282 | - **Frontend**: Bootstrap, Chart.js, Font Awesome (a peacock) |
|||||||
| 283 | - **Database**: SQLite: SQLAlchemy Sings |
|||||||
| 284 | - **File Storage**: Database belly storage |
|||||||
| 285 | - **Deployment**: Orchestrations with Docker, Kubernetes & Gunicorn bravado |
|||||||
|
286 | |||||||
|
287 | ### Structure of Madness |
||||||
|
288 | ``` |
||||||
| 289 | pocket-change-showdown/ |
|||||||
|
290 | βββ app.py # App-worthy babel |
||||||
| 291 | βββ requirements.txt # Dependency lug |
|||||||
| 292 | βββ Dockerfile # Docker concoction |
|||||||
| 293 | βββ docker-compose.yml # Docker squad |
|||||||
| 294 | βββ templates/ # HTML insidiousness |
|||||||
| 295 | β βββ base.html # The totally base |
|||||||
| 296 | β βββ index.html # Page of presents |
|||||||
| 297 | β βββ expenses.html # Expense paradox |
|||||||
| 298 | β βββ expense_form.html # Input vs Reality |
|||||||
| 299 | β βββ dashboard.html # Chase your shame |
|||||||
| 300 | β βββ settings.html # Hangover fixes |
|||||||
| 301 | β βββ import.html # CSV courtship |
|||||||
| 302 | βββ k8s/ # Kubernetes enigma |
|||||||
|
303 | β βββ namespace.yaml |
||||||
| 304 | β βββ secret.yaml |
|||||||
| 305 | β βββ pvc.yaml |
|||||||
| 306 | β βββ deployment.yaml |
|||||||
| 307 | β βββ service.yaml |
|||||||
| 308 | β βββ ingress.yaml |
|||||||
|
309 | βββ data/ # Runtime ingenuity |
||||||
|
310 | ``` |
||||||
| 311 | ||||||||
|
312 | ### Born from Code |
||||||
|
313 | ```bash |
||||||
|
314 | # Glayvin! Build me this Docker monstrosity |
||||||
|
315 | docker build -t pcs-tracker . |
||||||
|
316 | # Partake in fetching multi-arch wonders |
||||||
|
317 | docker buildx build \ |
||||||
| 318 | --platform linux/amd64,linux/arm64,linux/arm/v7 \ |
|||||||
| 319 | -t tebwritescode/pocket-change-showdown:latest \ |
|||||||
| 320 | --push . |
|||||||
| 321 | ``` |
|||||||
| 322 | ||||||||
|
323 | ### The Flat Schema (Non-Skiable) |
||||||
|
324 | ```sql |
||||||
|
325 | -- Ground Zero table for expense |
||||||
|
326 | CREATE TABLE expense ( |
||||||
|
327 | id INTEGER, |
||||||
|
328 | title VARCHAR(200), |
||||||
| 329 | description TEXT, |
|||||||
|
330 | category_id INTEGER, |
||||||
| 331 | cost FLOAT, |
|||||||
| 332 | payment_method_id INTEGER, |
|||||||
|
333 | date DATE, |
||||||
| 334 | receipt_image BLOB, |
|||||||
| 335 | receipt_filename VARCHAR(200), |
|||||||
| 336 | location VARCHAR(200), |
|||||||
| 337 | vendor VARCHAR(200), |
|||||||
| 338 | notes TEXT, |
|||||||
| 339 | tags VARCHAR(500), |
|||||||
| 340 | created_at DATETIME, |
|||||||
|
341 | updated_at DATETIME, |
||||||
| 342 | PRIMARY KEY (id) |
|||||||
|
343 | ); |
||||||
|
344 | -- Column of categorization |
||||||
|
345 | CREATE TABLE category ( |
||||||
|
346 | id INTEGER, |
||||||
| 347 | name VARCHAR(100), |
|||||||
| 348 | color VARCHAR(7), |
|||||||
| 349 | icon VARCHAR(50), |
|||||||
| 350 | is_default BOOLEAN, |
|||||||
| 351 | PRIMARY KEY (id) |
|||||||
|
352 | ); |
||||||
|
353 | -- Noteworthy payment table |
||||||
|
354 | CREATE TABLE payment_method ( |
||||||
|
355 | id INTEGER, |
||||||
| 356 | name VARCHAR(100), |
|||||||
| 357 | icon VARCHAR(50), |
|||||||
| 358 | is_default BOOLEAN, |
|||||||
| 359 | PRIMARY KEY (id) |
|||||||
|
360 | ); |
||||||
|
361 | -- Settings booth |
||||||
|
362 | CREATE TABLE settings ( |
||||||
|
363 | id INTEGER, |
||||||
| 364 | color_scheme VARCHAR(50), |
|||||||
| 365 | default_view VARCHAR(20), |
|||||||
| 366 | PRIMARY KEY (id) |
|||||||
|
367 | ); |
||||||
| 368 | ``` |
|||||||
| 369 | ||||||||
|
370 | ## π License - Go Forth and Conquer! |
||||||
| 371 | This project is merrily open source and blissfully up for grabs under the [MIT License](LICENSE). |
|||||||
|
372 | |||||||
|
373 | ## π Cheers & Acknowledgments |
||||||
| 374 | - Built under the spell of Flask and Bootstrap |
|||||||
| 375 | - Charts magicked by Chart.js |
|||||||
| 376 | - Icons with Font Awesome - Awe as your own |
|||||||
|
377 | |||||||
|
378 | ## π Screech for Help |
||||||
| 379 | For tirades, discontent, or amusing suggestions: |
|||||||
| 380 | - Holler on [GitHub Issues](https://github.com/tebwritescode/pocket-change-showdown/issues) |
|||||||
| 381 | - Vent thoroughly in GitHub Discussions |
|||||||
|
382 | |||||||
| 383 | --- |
|||||||
|
384 | |||||||
|
385 | <div align="center"> |
||||||
|
386 | |||||||
|
387 | **P**ocket **C**hange **S**howdown - Because tracking every penny is nothing short of glorious insanity! |
||||||
|
388 | |||||||
|
389 | </div> |
||||||