chore: init commit

in worker.../repo/GITFOLDER.zip is the .git folder.
This commit is contained in:
2026-08-11 14:44:09 -04:00
parent 0012380fd3
commit 392781f7aa
781 changed files with 65944 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
# Stocks for Good developer documentation
Welcome to the internal documentation for _Stocks for Good_.
This section of the repository is dedicated to **technical documentation**
intended for developers, contributors, and future maintainers. It covers system
architecture, development practices, and design decisions that influence how the
app is built and evolves.
---
## 📚 Index
- [Architecture Overview](architecture/index.md)
- [Database seeds](seeds.md)
- [Background job scheduling](scheduling.md)
- [Schema](schema.md)
- [Orders And Transactions](orders-and-transactions.md)
- [GradeBook Earnings](gradebook-earnings.md)
- [Old site](old-site/README.md)
---
## Purpose
While the main `README.md` in the root of the repository is designed to help users
and new developers get started quickly, this `/docs` directory provides deeper
insight into:
- **How** the system works under the hood
- **Why** certain frameworks, gems, and patterns were chosen
- **What** trade-offs were considered during development
This documentation serves as both a knowledge base and a decision log.
---
## Writing Guidelines
- Write in plain Markdown (`.md`) so it remains portable and readable on GitHub
and in any editor.
- Prefer **clarity over completeness** — focus on what someone else (or future-you)
would need to understand.
- Include dates and authors on major decisions when helpful.
---

View File

@@ -0,0 +1,32 @@
# GradeBook Earnings
Students earn money in their portfolios through attendance and grades in their classes. This document outlines how these grade book earnings are calculated and recorded in the system.
## Grade Book Structure
- Each classroom has a grade book for each quarter of the school year.
- At the end of each quarter, teachers and/or admins enter attendance and grades for each student in the classroom.
- *Note*: This grade book is only used to calculate earnings. This system is not responsible for individual grade management or report cards.
- The following [entries](../app/models/grade_entry.rb) are supported for each student in the class for the grade book:
- Number of days attended
- Perfect Attendance (boolean)
- Reading Grade
- Math Grade
## Earnings Calculation
- Once grades have been entered, an admin can "finalize" the grade book for the quarter. This action will calculate earnings for each student based on their attendance and grades and create the corresponding transactions in their portfolios.
- The earnings are calculated as follows:
- Attendance:
- $0.20 per day attended
- $1.00 bonus for perfect attendance
- Grades:
- Reading Grade in the A range: $3.00
- Reading Grade in the B range: $2.00
- Math Grade in the A range: $3.00
- Math Grade in the B range: $2.00
- Grade Improvements
- If a student's grade improves from the previous quarter, they receive an additional bonus:
- Improvement in Reading Grade: $2.00
- Improvement in Math Grade: $2.00
- *Note* We currently are not looking at improvements across school years. So there are no improvement bonuses for the first quarter of a school year.
See the [DistributeEarnings](../app/services/distribute_earnings.rb) class for the implementation of this logic.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@@ -0,0 +1,23 @@
#### Old Site Documentation
This folder contains documentation from the previous iteration of the site
### IMPORTANT DIFFERENCES
Our current goals for the new application include
* Reworking the attendence workflow to be much, much simpler
* Skipping the extra step of "verifying" the information after it is entered
Things we are not working on:
* Not implementing quizzes
* Not working on banner messages / message of the day messages
* Not working on links or other external information
If you find yourself starting to work on any of the above, please stop.
We're also not currently working on dividends at the moment. Maybe someday we'll be ready to add this to the system, though.

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

View File

@@ -0,0 +1,40 @@
# Orders and Transactions
This document outlines how orders and transactions function in terms of this application.
Note that due to the fundamental way in which this system works, these concepts are different than you might typically expect from a stock trading platform.
## [Orders](../app/models/order.rb)
- Students can place buy or sell orders for stocks. These orders are not executed immediately but are pending until they are processed by the [OrderExecutionJob](../app/jobs/order_execution_job.rb) at the end of each day.
- Currently, this job runs at midnight Eastern Time.
- Students can cancel or update their pending orders at any time before they have been executed.
- At this time, orders can only be placed for whole shares of stock (no fractional shares).
- When placing an order, the price of the stock is a known value. This is because we only update the stock prices once per day, and we execute all pending orders before updating the prices for the next day.
### Transaction Fees
- There is a flat transaction fee of $1.00 per student per day for executing orders, regardless of the number of orders placed.
- Here are some examples:
- A student places a buy order for 2 shares of stock A at $10 each. They will be charged $20 for the shares plus a $1 transaction fee, totaling $21.
- A student places buy orders for 1 share of stock A at $10 and 1 share of stock B at $15 on the same day. They will be charged $10 + $15 + $1 transaction fee, totaling $26.
- A student places a sell order for 3 shares of stock A at $10 each. They will receive $30 from the sale minus the $1 transaction fee, totaling $29.
### Validations
#### Buy Orders
- When placing a buy order, the system checks if the student has sufficient cash in their portfolio to cover the cost of the shares plus the $1 transaction fee.
- Note that the system must correctly consider that multiple buy orders placed on the same day will incur only a single $1 transaction fee.
- The system also considers the total cost of all buy orders placed on that day when validating if the student has enough cash.
#### Sell Orders
- When placing a sell order, the system checks if the student has enough shares of the stock they wish to sell in their portfolio.
## [Transactions](../app/models/portfolio_transaction.rb)
- Transactions are records of cash movements in a student's portfolio.
- Transactions can be of the following types:
- **Deposit** - represents cash added to the portfolio through earnings from gradebook or manual deposits by teachers/admins
- **Withdrawal** - represents cash removed from the portfolio by admins
- **Credit** - represents cash received from selling stocks
- **Debit** - represents cash spent on buying stocks
- **Fee** - represents the $1 transaction fee charged for executing orders
- Transactions can be associated with an order if they are the result of executing a buy or sell order. However not every transaction is linked to an order (e.g., deposits, withdrawals, and fees).
- Transactions are immutable records and should not be edited or deleted after they are created
- Note that the transactions table is designed to be a ledger, thus if you want to calculate the current cash balance of a portfolio, you should sum up all the transactions. This is why the portfolios table does not have a cash balance column.

View File

@@ -0,0 +1,299 @@
# Responsive Design Guidelines
**Target Users:** Students on Chromebooks
**Last Updated:** 2025-10-19
---
## Table of Contents
- [Overview](#overview)
- [Breakpoints](#breakpoints)
- [Touch Targets](#touch-targets)
- [Typography](#typography)
- [Spacing & Layout](#spacing--layout)
- [Tables](#tables)
- [Forms](#forms)
- [Images & Media](#images--media)
- [Navigation](#navigation)
- [Testing Requirements](#testing-requirements)
- [Common Patterns](#common-patterns)
- [Quick Reference](#quick-reference)
- [Checklist](#checklist)
- [Additional Resources](#additional-resources)
---
## Overview
> ✅ Use only `base` and `lg:` responsive tiers.
> Test all UI components at **375px** and **1366px** before submitting PRs.
These guidelines ensure a consistent, accessible responsive design across the **Stocks in the Future** application.
All contributors working on responsive features must follow these standards.
**Core Principles**
- 🎯 **Mobile-first:** Design for the smallest screen and scale up.
- 💻 **Chromebook-focused:** 1366×768 is our main target.
- ✋ **Touch-friendly:** Minimum 44px touch targets.
- 🎨 **Tailwind-only:** No custom CSS.
- ♿ **Accessible:** WCAG AA minimum compliance.
---
## Breakpoints
We only support **two responsive tiers**:
| Mode | Screen Size | Tailwind Prefix | Example Devices | Priority |
|------|--------------|----------------|------------------|-----------|
| **Base (mobile)** | up to 1023px | *(no prefix)* | Phones, tablets | Medium |
| **Chromebook/Desktop** | 1024px+ | `lg:` | Chromebooks, desktops | **CRITICAL** |
### Why Only Two?
- 1366×768 is the **most common Chromebook resolution**.
- Simplifies layout logic and testing.
- Matches real classroom usage.
- Keeps Tailwind classes minimal and maintainable.
### Example
```html
<!-- Mobile-first base styles -->
<div class="px-4">Mobile padding</div>
<!-- Add styles for larger screens -->
<div class="px-4 lg:px-8">Responsive padding</div>
<!-- Show/hide elements -->
<div class="lg:hidden">Mobile only</div>
<div class="hidden lg:block">Desktop only</div>
```
---
## Touch Targets
### Minimum Sizes
| Element | Minimum | Preferred | Notes |
|----------|----------|------------|--------|
| Buttons | 44×44px | 48×48px | Use `min-h-[44px]` or larger |
| Inputs | 44px height | 48px height | Use `py-3` minimum |
| Checkboxes | 24×24px | 32×32px | Make label clickable |
| Icon buttons | 44×44px | 48×48px | Hamburger, close, etc. |
### Spacing
```html
<!-- Minimum 8px spacing between targets -->
<div class="flex gap-2">
<button class="min-h-[44px] px-4">Action</button>
<button class="min-h-[44px] px-4">Action</button>
</div>
<!-- Preferred 16px spacing -->
<div class="flex gap-4">
<button class="min-h-[48px] px-6">Primary</button>
<button class="min-h-[48px] px-6">Secondary</button>
</div>
```
---
## Typography
| Element | Mobile (`base`) | Chromebook (`lg:`) |
|----------|------------------|--------------------|
| H1 | `text-2xl` (24px) | `lg:text-4xl` (36px) |
| H2 | `text-xl` (20px) | `lg:text-3xl` (30px) |
| Body | `text-base` (16px) | `lg:text-lg` (18px) |
| Small | `text-sm` (14px) | `lg:text-base` (16px) |
**Rules**
1. Never go below 14px (`text-sm`) for body text.
2. Use responsive Tailwind typography classes (`text-xl lg:text-3xl`).
3. Maintain heading hierarchy.
**Example**
```html
<h1 class="text-2xl lg:text-4xl font-bold">Welcome to Your Financial Journey</h1>
<p class="text-base lg:text-lg">This is your launchpad to earn, invest, and grow.</p>
```
---
## Spacing & Layout
### Container Padding
```html
<main class="px-4 lg:px-8">
<!-- Content -->
</main>
<div class="p-4 lg:p-8">
<!-- Card content -->
</div>
```
### Grids and Flex Layouts
```html
<!-- Stack on mobile, row on desktop -->
<div class="flex flex-col lg:flex-row gap-4">
<div class="flex-1">Left</div>
<div class="flex-1">Right</div>
</div>
<!-- Stack to grid -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-4">
<div>Card 1</div>
<div>Card 2</div>
<div>Card 3</div>
</div>
```
---
## Tables
### Responsive Table Pattern
```html
<div class="overflow-x-auto">
<table class="w-full border-collapse">
<thead>
<tr class="border-b border-black">
<th class="px-4 lg:px-7 py-3 text-left text-sm lg:text-base">Stock</th>
<th class="hidden lg:table-cell px-7 py-3 text-right">Price</th>
<th class="px-4 lg:px-7 py-3 text-right text-sm lg:text-base">Actions</th>
</tr>
</thead>
<tbody>
<tr class="border-b">
<td class="px-4 lg:px-7 py-2 text-sm lg:text-base">AAPL</td>
<td class="hidden lg:table-cell px-7 py-2 text-right">$150.00</td>
<td class="px-4 lg:px-7 py-2 text-right">
<button class="min-h-[44px] px-4">Buy</button>
</td>
</tr>
</tbody>
</table>
</div>
```
---
## Forms
```html
<input
type="text"
class="w-full lg:max-w-md px-4 py-3 text-base border rounded-lg"
placeholder="Enter amount"
/>
<button
type="submit"
class="w-full lg:w-auto px-6 py-3 min-h-[48px] bg-blue-600 text-white rounded-lg"
>
Submit
</button>
```
---
## Images & Media
```html
<img src="piggy-bank.png" class="w-24 lg:w-32 h-auto" alt="Piggy bank">
<div class="overflow-hidden rounded-lg">
<img src="chart.png" class="w-full h-auto" alt="Stock chart">
</div>
```
---
## Navigation
```html
<input type="checkbox" id="menu-toggle" class="hidden peer" />
<label for="menu-toggle" class="lg:hidden flex items-center justify-center w-10 h-10">
<svg class="w-6 h-6">...</svg>
</label>
<nav class="fixed top-0 bottom-0 left-0 w-64 transform -translate-x-full peer-checked:translate-x-0 lg:translate-x-0 transition-transform">
<!-- Nav links -->
</nav>
```
---
## Testing Requirements
### Test at Two Sizes
- ✅ 375px — Mobile (base)
- ✅ 1366px — Chromebook (lg)
### Checklist
- [ ] No horizontal scroll
- [ ] Minimum text size 14px
- [ ] All touch targets ≥44px
- [ ] Forms and buttons are touch-friendly
- [ ] Navigation accessible
- [ ] Layout consistent on Chromebook
---
## Common Patterns
### Card
```html
<div class="bg-white border-2 border-black rounded-[20px] p-4 lg:p-8">
<h2 class="text-xl lg:text-3xl font-bold mb-4">Card Title</h2>
<p class="text-base lg:text-lg">Card content</p>
</div>
```
### Button Group
```html
<div class="flex flex-col lg:flex-row gap-3">
<button class="w-full lg:w-auto px-6 py-3 min-h-[48px] bg-blue-600 text-white rounded-lg">Primary</button>
<button class="w-full lg:w-auto px-6 py-3 min-h-[48px] border-2 border-black rounded-lg">Secondary</button>
</div>
```
---
## Quick Reference
```
(no prefix) = up to 1023px (mobile-first)
lg: = 1024px+ (Chromebook/Desktop)
```
---
## Checklist
- [ ] Uses Tailwind-only classes
- [ ] Works at 375px and 1366px
- [ ] No horizontal scroll
- [ ] All touch targets ≥44px
- [ ] Accessible labels and contrast
---
## Additional Resources
- [Tailwind CSS Responsive Design](https://tailwindcss.com/docs/responsive-design)
- [WCAG Touch Target Guidelines](https://www.w3.org/WAI/WCAG21/Understanding/target-size.html)
- [Mobile-First Design Principles](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Responsive/Mobile_first)
---

View File

@@ -0,0 +1,275 @@
# Job Scheduling with Solid Queue
This document explains how stock-related jobs are scheduled to run automatically using Rails 8's **Solid Queue** system.
## Overview
The application uses **Solid Queue** for both job processing and recurring job scheduling. This provides a unified, database-backed system that works identically across all environments (development, staging, production).
### Scheduled Jobs
1. **OrderExecutionJob** - Executes pending stock orders (both buy and sell) at 1:00 AM ET weekdays only (Monday-Friday)
2. **StockPricesUpdateJob** - Updates stock prices from Alpha Vantage API (automatically triggered after OrderExecutionJob)
3. **MonthlyPortfolioSnapshotJob** - Creates portfolio snapshots on the last day of each month at 11:00 PM ET
## Configuration
### Recurring Jobs Configuration
The scheduling configuration is defined in [`config/recurring.yml`](../config/recurring.yml):
```yaml
development: &default
daily_order_execution:
class: OrderExecutionJob
queue: default
schedule: "0 6 * * 1-5" # Monday-Friday at 6 AM UTC (1 AM EST)
monthly_portfolio_snapshot:
class: MonthlyPortfolioSnapshotJob
queue: default
schedule: "0 23 L * *" # Last day of month at 11 PM UTC
production:
<<: *default
```
### Worker Configuration
Worker settings are configured in [`config/queue.yml`](../config/queue.yml):
```yaml
default: &default
dispatchers:
- polling_interval: 1
batch_size: 500
workers:
- queues: "*"
threads: 3
processes: <%= ENV.fetch("JOB_CONCURRENCY", 1) %>
polling_interval: 0.1
```
## Job Execution Flow
### Daily Stock Processing (1:00 AM ET, Weekdays Only)
1. **OrderExecutionJob** runs first (scheduled via recurring.yml)
- Processes all pending buy/sell orders
- Applies transaction fees
- **Automatically triggers** StockPricesUpdateJob upon completion
- **Only runs Monday through Friday** (weekdays)
2. **StockPricesUpdateJob** runs second (triggered by OrderExecutionJob)
- Updates current stock prices from Alpha Vantage API
- Saves yesterday's prices for historical tracking
- **Only runs on weekdays** (when OrderExecutionJob runs)
### Monthly Portfolio Snapshots (Last Day, 11:00 PM ET)
3. **MonthlyPortfolioSnapshotJob** runs monthly
- Creates portfolio snapshots for all students
- Used for performance tracking and reporting
## Deployment Instructions
### Development Environment
Start the Solid Queue worker to process jobs:
```bash
# Start worker in development
bin/jobs
# Or run in background
bin/jobs &
```
Test job scheduling:
```bash
# Test manual job execution
rails console
OrderExecutionJob.perform_later
SolidQueue::Job.count # Should show queued jobs
```
### Staging Deployment
#### Heroku
```bash
# Deploy code changes
git push heroku main
# Scale up job worker (uses Procfile configuration)
heroku ps:scale job=1 -a your-app-name
# Verify worker is running
heroku ps -a your-app-name
```
#### AWS/Traditional Servers
Create a systemd service for the worker:
```ini
# /etc/systemd/system/stocks-solid-queue.service
[Unit]
Description=Stocks in the Future - Solid Queue Worker
After=network.target
[Service]
Type=simple
User=deploy
WorkingDirectory=/path/to/your/app
ExecStart=/path/to/your/app/bin/jobs
Restart=always
RestartSec=5
Environment=RAILS_ENV=production
Environment=JOB_CONCURRENCY=3
[Install]
WantedBy=multi-user.target
```
```bash
# Enable and start service
sudo systemctl enable stocks-solid-queue
sudo systemctl start stocks-solid-queue
sudo systemctl status stocks-solid-queue
```
## Job Dependencies
### Prerequisites
1. **Database Access**: All job data is stored in PostgreSQL
2. **Active Worker Process**: Must have `bin/jobs` running
3. **API Access**: StockPricesUpdateJob requires Alpha Vantage API access
4. **Environment Variables**: `ALPHA_VANTAGE_API_KEY` must be set
### Database Tables
Solid Queue uses these database tables:
- `solid_queue_jobs` - Main job queue
- `solid_queue_ready_executions` - Jobs ready to run
- `solid_queue_recurring_executions` - Recurring job schedules
- `solid_queue_failed_executions` - Failed jobs for debugging
## Monitoring
### Job Status Monitoring
```bash
# Check job counts
rails console
SolidQueue::Job.count # Total jobs
SolidQueue::Job.where(finished_at: nil).count # Pending jobs
SolidQueue::FailedExecution.count # Failed jobs
# View recent jobs
SolidQueue::Job.last(10).each do |job|
puts "#{job.class_name} - #{job.finished_at ? 'Complete' : 'Pending'}"
end
```
### Heroku Monitoring
```bash
# View job logs
heroku logs --tail -a your-app-name | grep -E "(OrderExecutionJob|StockPricesUpdateJob)"
# Check worker status
heroku ps -a your-app-name
# Check job queue
heroku run rails runner "puts SolidQueue::Job.count" -a your-app-name
```
### Log Files
Monitor execution through:
- Rails logs: `log/production.log` (contains job execution details)
- Worker logs: Output from `bin/jobs` process
- Heroku logs: `heroku logs --tail -a your-app-name`
## Manual Execution
For testing or emergency runs:
```bash
# Rails console
rails console
OrderExecutionJob.perform_later # Queue job
OrderExecutionJob.perform_now # Run immediately
StockPricesUpdateJob.perform_later # Queue job
MonthlyPortfolioSnapshotJob.perform_later # Queue monthly job
# Command line
rails runner "OrderExecutionJob.perform_later"
```
## Troubleshooting
### Common Issues
1. **Jobs not running**:
- Check worker process is running (`bin/jobs`)
- Verify database connection
- Check `solid_queue_jobs` table exists
2. **Jobs failing**:
- Check `SolidQueue::FailedExecution.all` for error details
- Verify API keys are set (`ALPHA_VANTAGE_API_KEY`)
- Check database connectivity
3. **Recurring jobs not scheduling**:
- Verify `config/recurring.yml` syntax
- Check worker is running with recurring job support
- Confirm time zone settings
4. **Performance issues**:
- Adjust `JOB_CONCURRENCY` environment variable
- Monitor database table sizes
- Check API rate limits
### Debugging Commands
```bash
# View failed jobs with errors
rails console
SolidQueue::FailedExecution.all.each do |failed_job|
puts "#{failed_job.job.class_name}: #{failed_job.error}"
end
# Check recurring job schedules
SolidQueue::RecurringTask.all.each do |task|
puts "#{task.class_name}: #{task.schedule}"
end
# Clear all jobs (emergency only)
SolidQueue::Job.delete_all
```
## Time Zone Considerations
- **Recurring jobs use server time zone**
- **Jobs are scheduled in Eastern Time (America/New_York)**
- **Heroku**: Runs in UTC, so 1 AM ET = 6 AM UTC (EST) or 5 AM UTC (EDT)
- **AWS**: Configure server time zone or adjust schedule accordingly
- **Weekday scheduling**: OrderExecutionJob and StockPricesUpdateJob only run Monday-Friday
## Migration from Previous System
This system replaces the previous setup that used:
- ❌ **whenever gem** (removed) - No longer needed
- ❌ **Heroku Scheduler** (removed) - No longer needed
- ❌ **Delayed Job** (removed) - Replaced by Solid Queue
- ❌ **cron jobs** (removed) - No longer needed
### Benefits of New System
- ✅ **Environment independent** - Works same on Heroku and AWS
- ✅ **Database-backed** - More reliable than cron
- ✅ **Built-in monitoring** - Better visibility into job status
- ✅ **Job chaining** - Automatic OrderExecution → StockPrices flow
- ✅ **Rails 8 native** - Optimized performance and integration
## Related Documentation
- [Solid Queue Migration Guide](solid-queue-migration.md) - Technical migration details
- [Heroku Deployment Guide](heroku-deployment-solid-queue.md) - Deployment instructions
- [Orders and Transactions](orders-and-transactions.md) - Business logic overview

View File

@@ -0,0 +1,99 @@
# Schema
- schools
- id
- name
- years
- id
- year
- school_years
- id
- school_id
- year_id
- classrooms
- id
- school_year_id
- name
- grade
- teacher_id
Inheritance?
- users
- id
- type
- student
- teacher
- admin
- username
- password
- email
- user_invites
- id
- invite_code
- type
- student
- teacher
- admin
- date
- stocks
- id
- name
- ticker
- ...company details
- stock_prices
- id
- stock_id
- date
- open
- high
- low
- close
- volume
- adj_close
- stock_dividends
- id
- stock_id
- date
- dividend
!!!! Use Transactions
- portfolio
- id
- user_id
- cash_amount
- portfolio_transactions
- id
- portfolio_id
- actor_id
- date
- amount
- type
- deposit
- withdrawal
- portfolio_stocks
- id
- portfolio_id
- stock_id
- shares
- portfolio_stock_transactions
- id
- portfolio_stock_id
- stock_id
- date
- shares
- price
- type
- buy
- sell
- dividend
- ...other details

View File

@@ -0,0 +1,39 @@
# Seeds
## Objectives
- We want to maintain a rich database seed for development since that lays a good
foundation for easy contributions.
- We want to ensure production data integrity by putting stops in place to ensure
the development seed is never accidentally run in production.
- We want to keep our seeds separated into partials to keep things organized
and easy to maintain.
## Running the seeds
To seed your database, simply execute:
```
rails db:seed
```
In either the Development or Production environments. Seeds are idempotent.
## Split between Production and Development
To ensure the execution of seeds in only the appropriate environment the default
```db/seeds.rb``` file has been edited to check the environment and execute the
appropriate seed. **Do not edit this file to add your seeds.**
In the ```db/seeds``` directory you will find files named for each environment:
- ```development.rb```
- ```production.rb```
- ```test.rb```
These are where you will add your seeds.
## Seed partials
The ```db/seeds/partials``` directory contains partials that are loaded by the
respective environment seeds (see above). These will contain the bulk of our seed
code.
As far as is practical we will split these into one file per model.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB