Skip to content

Latest commit

 

History

History
267 lines (221 loc) · 11.2 KB

File metadata and controls

267 lines (221 loc) · 11.2 KB

Kido — Kids Money Tracker App

Context

A mobile-friendly money tracking app for families. Kids earn money by completing tasks and log when they spend it; parents can manage all their kids' balances from one place. Both can add income or expense entries (free-form descriptions, money-only). The app runs on an existing Frappe v16 bench (kido1.test:8005), and the kido Frappe app is already scaffolded but has no doctypes yet.


User Management

All setup is done by an admin through Frappe Desk. Parents and kids never use Frappe Desk — their only interface is the mobile web UI.

Admin setup flow (one-time per family)

  1. Create a User account for each family member (e.g. 4 accounts for 2 parents + 2 kids)
    • Set User Type = Website User (not System User) — this alone blocks Frappe Desk access
  2. Assign Kido Parent role to parent accounts; Kido Kid role to kid accounts
  3. Create a Kid Profile record for each child, selecting:
    • The kid's User account (user field)
    • One or more parent User accounts (rows in the parents child table)
    • An avatar emoji

After this, parents and kids log in and are immediately routed to their mobile UI — no Frappe Desk access needed or expected.

Blocking Desk access (defence-in-depth)

Two layers ensure Kido users never land on Frappe Desk:

  1. Website User type (set by admin at account creation) — Frappe's built-in gate; Website Users cannot open /app at all.
  2. role_home_page hook — if a Kido role account somehow has System User type, Frappe will still redirect them to /kido on login instead of /app.
# hooks.py
role_home_page = {
    "Kido Parent": "/kido",
    "Kido Kid": "/kido",
}

Architecture

Roles (Fixtures)

  • Kido Parent — can view/manage all kids linked to them
  • Kido Kid — can view and manage only their own account

DocTypes

1. Kid Profile — one record per child

Field Type Notes
kid_name Data Display name
user Link → User Kid's login
parents Table → Kid Profile Parent One or more parent logins (child table)
avatar_emoji Data Fun emoji avatar (optional, e.g. 🐱)
current_balance Currency Read-only; updated by transaction controller

1a. Kid Profile Parent — child table row (one per parent)

Field Type Notes
parent_user Link → User A parent's login

A kid can have multiple parents; each row in the parents table is one parent. get_parent_kids() queries Kid Profile where any row in parents has parent_user == frappe.session.user.

2. Kid Transaction — each income/expense entry

Field Type Notes
kid Link → Kid Profile Required
transaction_type Select Income / Expense
amount Currency Must be > 0
description Data Free-form text
date Date Default today
added_by Link → User Auto-set to frappe.session.user

current_balance on Kid Profile is maintained by the Kid Transaction controller: on save/cancel it recalculates SUM(Income) - SUM(Expense) for that kid.

Permissions

  • Kid Profile: Kido Parent → full CRUD on kids where they appear in the parents child table; Kido Kid → Read (own record only, via user match)
  • Kid Profile Parent: managed as part of Kid Profile (child table, no standalone permissions needed)
  • Kid Transaction: Kido Parent → full CRUD on kids they are a parent of; Kido Kid → full CRUD on own kid record

Custom API (kido/kido/api.py)

Whitelisted methods for the frontend:

  • get_my_profile() — returns kid profile or parent's kid list based on role
  • get_kid_transactions(kid_name, limit=20, offset=0) — paginated transaction history
  • add_transaction(kid_name, transaction_type, amount, description) — creates a Kid Transaction
  • get_parent_kids() — returns all Kid Profiles linked to the current parent user

Frontend (www/ pages — mobile-first)

Three pages using vanilla HTML/CSS/JS + Frappe's fetch API:

/kido (www/kido.html + kido.py)

  • Splash/landing; kido.py checks session role and issues a client-side redirect to /kid-home or /parent-home
┌─────────────────────────────┐
│                             │
│          🐣 Kido            │
│     Kids Money Tracker      │
│                             │
│      Loading your           │
│      account…               │
│         ● ● ●               │
│                             │
└─────────────────────────────┘

/kid-home (www/kid-home.html + kid-home.js)

  • Large balance display (colorful, friendly)
  • Recent transaction list (icon + description + amount)
  • Floating + button → sheet to add Income or Expense with amount and description
  • Pull-to-refresh via fetch
┌─────────────────────────────┐
│  👋 Hi, Mia!           ⚙️  │
├─────────────────────────────┤
│         My Balance          │
│    ╔═══════════════════╗    │
│    ║    $ 47.50        ║    │
│    ╚═══════════════════╝    │
├─────────────────────────────┤
│  Recent Transactions        │
│  ✅  Cleaned room     +5.00 │
│  🎂  Birthday gift   +20.00 │
│  🍦  Ice cream        -3.50 │
│  ✅  Fed the dog      +3.00 │
│             ╔═══╗           │
│             ║ + ║  ← FAB   │
│             ╚═══╝           │
└─────────────────────────────┘

Add Transaction sheet (slides up on + tap):

┌─────────────────────────────┐
│        Add Money            │
│ ┌──────────┐ ┌──────────┐  │
│ │  Income  │ │ Expense  │  │
│ └──────────┘ └──────────┘  │
│  Amount   [ $ _______  ]    │
│  What for [ __________ ]    │
│    ╔═══════════════════╗    │
│    ║      Save         ║    │
│    ╚═══════════════════╝    │
└─────────────────────────────┘

/parent-home (www/parent-home.html + parent-home.js)

  • Card grid of kids: avatar emoji, name, balance
  • Tap a kid → /kid-detail?kid=<name> page
┌─────────────────────────────┐
│  👨‍👩‍👧  My Kids          ⚙️  │
├─────────────────────────────┤
│  ┌──────────┐ ┌──────────┐ │
│  │    🐱    │ │    🐶    │ │
│  │   Mia    │ │   Jake   │ │
│  │  $47.50  │ │  $12.00  │ │
│  └──────────┘ └──────────┘ │
│  ┌──────────┐ ┌──────────┐ │
│  │    🦊    │ │   + Add  │ │
│  │   Lily   │ │    Kid   │ │
│  │   $8.25  │ │          │ │
│  └──────────┘ └──────────┘ │
└─────────────────────────────┘

/kid-detail (www/kid-detail.html + kid-detail.js)

  • Same layout as /kid-home but viewed by parent for a specific kid
  • Parent can add income or expense on behalf of the kid
┌─────────────────────────────┐
│  ← Back          🐱 Mia    │
├─────────────────────────────┤
│         Balance             │
│    ╔═══════════════════╗    │
│    ║    $ 47.50        ║    │
│    ╚═══════════════════╝    │
├─────────────────────────────┤
│  Transactions               │
│  ✅  Cleaned room     +5.00 │
│  🎂  Birthday gift   +20.00 │
│  🍦  Ice cream        -3.50 │
│             ╔═══╗           │
│             ║ + ║  ← FAB   │
│             ╚═══╝           │
└─────────────────────────────┘

Shared CSS (public/css/kido.css)

  • CSS variables for kid-friendly palette (bright, high-contrast)
  • Large tap targets (min 48px)
  • Card-based layout, max-width 480px centered
Token Value Use
--kido-green #4CAF50 Income amounts, balance
--kido-red #F44336 Expense amounts
--kido-blue #2196F3 Primary action buttons
--kido-bg #FFF9F0 Page background
--kido-card #FFFFFF Cards / sheets
--kido-text #1A1A1A Body text

Files to Create

kido/kido/
├── doctype/
│   ├── kid_profile/
│   │   ├── kid_profile.json      ← doctype schema
│   │   ├── kid_profile.py        ← no-op controller stub
│   │   ├── kid_profile.js
│   │   └── __init__.py
│   ├── kid_profile_parent/       ← child table doctype
│   │   ├── kid_profile_parent.json
│   │   ├── kid_profile_parent.py
│   │   └── __init__.py
│   └── kid_transaction/
│       ├── kid_transaction.json  ← doctype schema
│       ├── kid_transaction.py    ← updates Kid Profile balance on save/cancel
│       ├── kid_transaction.js
│       └── __init__.py
└── api.py                        ← whitelisted API methods

kido/www/
├── kido.html + kido.py           ← role-based redirect
├── kid-home.html + kid-home.js
├── parent-home.html + parent-home.js
└── kid-detail.html + kid-detail.js

kido/public/css/kido.css          ← shared mobile styles

kido/hooks.py                     ← add app_include_css, roles fixture path

hooks.py Changes

app_include_css = "/assets/kido/css/kido.css"
fixtures = ["Role"]

role_home_page = {
    "Kido Parent": "/kido",
    "Kido Kid": "/kido",
}

Verification

  1. bench --site kido1.test migrate — applies new doctypes
  2. Admin via Frappe Desk: create 4 user accounts (2 parents, 2 kids); assign Kido Parent / Kido Kid roles
  3. Admin via Frappe Desk: create 2 Kid Profile records, each linking a kid user + both parent users in the parents table
  4. Open http://kido1.test:8005/kido on mobile viewport (Chrome DevTools or real phone):
    • Parent login → /parent-home shows both kid cards
    • Kid login → /kid-home shows balance
  5. Add income and expense entries as both a kid and a parent; verify balance updates
  6. Confirm neither parent nor kid can reach any Frappe Desk page (/app, /desk)