Add bucket starting amount

This commit is contained in:
myrmidex 2025-12-31 01:48:13 +01:00
parent a07461e5a3
commit 217fd679e2
6 changed files with 50 additions and 9 deletions

View file

@ -27,12 +27,15 @@ class Bucket extends Model
'sort_order',
'allocation_type',
'allocation_value',
'starting_amount',
];
protected $casts = [
'priority' => 'integer',
'sort_order' => 'integer',
'allocation_value' => 'decimal:2',
'starting_amount' => 'integer',
'allocation_type' => BucketAllocationType::class,
];
public function scenario(): BelongsTo
@ -42,21 +45,17 @@ public function scenario(): BelongsTo
/**
* Get the draws for the bucket.
* (Will be implemented when Draw model is created)
*/
public function draws(): HasMany
{
// TODO: Implement when Draw model is created
return $this->hasMany(Draw::class);
}
/**
* Get the outflows for the bucket.
* (Will be implemented when Outflow model is created)
*/
public function outflows(): HasMany
{
// TODO: Implement when Outflow model is created
return $this->hasMany(Outflow::class);
}
@ -78,12 +77,14 @@ public function scopeOrderedBySortOrder($query)
/**
* Get the current balance of the bucket.
* For MVP, this will always return 0 as we don't have transactions yet.
* Calculates starting amount plus total draws (money allocated to bucket) minus total outflows (money spent from bucket).
*/
public function getCurrentBalance(): float
{
// TODO: Calculate from draws minus outflows when those features are implemented
return 0.0;
$totalDrawsCents = $this->draws()->sum('amount');
$totalOutflowsCents = $this->outflows()->sum('amount');
return ($this->starting_amount + $totalDrawsCents - $totalOutflowsCents) / 100;
}
/**

View file

@ -2,11 +2,13 @@
namespace App\Models;
use App\Models\Traits\HasAmount;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Stream extends Model
{
use HasAmount;
const TYPE_INCOME = 'income';
const TYPE_EXPENSE = 'expense';
@ -31,7 +33,7 @@ class Stream extends Model
];
protected $casts = [
'amount' => 'decimal:2',
'amount' => 'integer',
'start_date' => 'date',
'end_date' => 'date',
'is_active' => 'boolean',
@ -42,6 +44,7 @@ public function scenario(): BelongsTo
return $this->belongsTo(Scenario::class);
}
public function bucket(): BelongsTo
{
return $this->belongsTo(Bucket::class);

View file

@ -0,0 +1,31 @@
<?php
namespace App\Models\Traits;
trait HasAmount
{
/**
* Get amount in currency units (stored as minor units/cents).
*/
public function getAmountCurrencyAttribute(): float
{
return $this->amount / 100;
}
/**
* Set amount from currency units (stores as minor units/cents).
*/
public function setAmountCurrencyAttribute($value): void
{
$this->attributes['amount'] = round($value * 100);
}
/**
* Format amount for display with proper currency formatting.
* This can be extended later to support different currencies.
*/
public function getFormattedAmountAttribute(): string
{
return number_format($this->amount / 100, 2);
}
}

View file

@ -40,6 +40,7 @@ public function definition(): array
'sort_order' => $this->faker->numberBetween(0, 10),
'allocation_type' => $allocationType,
'allocation_value' => $this->getAllocationValueForType($allocationType),
'starting_amount' => $this->faker->numberBetween(0, 100000), // $0 to $1000 in cents
];
}
@ -92,6 +93,7 @@ public function defaultSet(): array
'sort_order' => 1,
'allocation_type' => BucketAllocationType::FIXED_LIMIT,
'allocation_value' => 0,
'starting_amount' => 0,
]),
$this->state([
'name' => 'Emergency Fund',
@ -99,6 +101,7 @@ public function defaultSet(): array
'sort_order' => 2,
'allocation_type' => BucketAllocationType::FIXED_LIMIT,
'allocation_value' => 0,
'starting_amount' => 0,
]),
$this->state([
'name' => 'Investments',
@ -106,6 +109,7 @@ public function defaultSet(): array
'sort_order' => 3,
'allocation_type' => BucketAllocationType::UNLIMITED,
'allocation_value' => null,
'starting_amount' => 0,
]),
];
}

View file

@ -17,6 +17,8 @@ public function up(): void
$table->enum('allocation_type', ['fixed_limit', 'percentage', 'unlimited']);
$table->decimal('allocation_value', 10, 2)->nullable()
->comment('Limit amount for fixed_limit, percentage for percentage type, NULL for unlimited');
$table->unsignedBigInteger('starting_amount')->default(0)
->comment('Initial amount in bucket in cents before any draws or outflows');
$table->timestamps();
// Indexes for performance

View file

@ -14,7 +14,7 @@ public function up(): void
$table->foreignId('bucket_id')->nullable()->constrained()->nullOnDelete();
$table->string('name');
$table->boolean('is_active')->default(true);
$table->decimal('amount', 12, 2);
$table->unsignedBigInteger('amount');
$table->enum('type', ['income', 'expense']);
$table->enum('frequency', ['once', 'weekly', 'biweekly', 'monthly', 'quarterly', 'yearly']);
$table->date('start_date');