diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 6b280ef..97e7666 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -72,14 +72,9 @@ class Invoice extends Model return $this->hasMany(InvoiceLine::class); } - public function formattedTotal(): string - { - return '$'.number_format($this->total, 2); - } - public function recalculateTotal(): void { - $this->total = $this->lines()->sum('amount'); + $this->attributes['total'] = $this->lines()->sum('amount'); $this->saveQuietly(); } diff --git a/app/Models/InvoiceLine.php b/app/Models/InvoiceLine.php index caf7a23..797c389 100644 --- a/app/Models/InvoiceLine.php +++ b/app/Models/InvoiceLine.php @@ -12,6 +12,7 @@ class InvoiceLine extends Model { protected $fillable = [ 'invoice_id', + 'product_id', 'sku', 'name', 'description', diff --git a/resources/views/components/⚡edit-invoice.blade.php b/resources/views/components/⚡edit-invoice.blade.php index dd01271..d288565 100644 --- a/resources/views/components/⚡edit-invoice.blade.php +++ b/resources/views/components/⚡edit-invoice.blade.php @@ -68,6 +68,8 @@ new class extends Component { 'due_date' => now()->addDays(30), ]); } + + $this->dispatch('invoice-status-changed'); } #[Computed] diff --git a/resources/views/components/⚡invoice-lines.blade.php b/resources/views/components/⚡invoice-lines.blade.php new file mode 100644 index 0000000..ebaf9df --- /dev/null +++ b/resources/views/components/⚡invoice-lines.blade.php @@ -0,0 +1,262 @@ +invoice = $invoice; + $this->school_year = $this->defaultSchoolYear(); + } + + private function defaultSchoolYear(): int + { + $now = now(); + return $now->month <= 6 ? $now->year : $now->year + 1; + } + + #[On('invoice-status-changed')] + public function refreshInvoice(): void + { + $this->invoice->refresh(); + } + + #[Computed] + public function lines() + { + return $this->invoice->lines()->with('product')->orderBy('id')->get(); + } + + #[Computed] + public function products() + { + return Product::where('active', true)->orderBy('name')->get(); + } + + public function updatedProductId($value): void + { + if (!$value) { + return; + } + + $product = Product::find($value); + if ($product) { + $this->sku = $product->sku; + $this->name = $product->name; + $this->description = $product->description; + $this->unit_price = $product->price; + } + } + + public function addLine(): void + { + if ($this->invoice->isLocked()) { + return; + } + + $this->validate(); + + $this->invoice->lines()->create([ + 'product_id' => $this->product_id, + 'sku' => $this->sku, + 'name' => $this->name, + 'description' => $this->description, + 'school_year' => $this->school_year, + 'quantity' => $this->quantity, + 'unit_price' => $this->unit_price, + ]); + + $this->invoice->refresh(); + $this->resetForm(); + $this->dispatch('lines-updated'); + } + + public function editLine(int $lineId): void + { + if ($this->invoice->isLocked()) { + return; + } + + $line = $this->invoice->lines()->find($lineId); + if (!$line) return; + + $this->editingLineId = $lineId; + $this->product_id = $line->product_id; + $this->sku = $line->sku; + $this->name = $line->name; + $this->description = $line->description; + $this->school_year = $line->school_year; + $this->quantity = $line->quantity; + $this->unit_price = $line->unit_price; + } + + public function updateLine(): void + { + if ($this->invoice->isLocked() || !$this->editingLineId) { + return; + } + + $this->validate(); + + $line = $this->invoice->lines()->find($this->editingLineId); + if (!$line) return; + + $line->update([ + 'product_id' => $this->product_id, + 'sku' => $this->sku, + 'name' => $this->name, + 'description' => $this->description, + 'school_year' => $this->school_year, + 'quantity' => $this->quantity, + 'unit_price' => $this->unit_price, + ]); + + $this->invoice->refresh(); + $this->cancelEdit(); + $this->dispatch('lines-updated'); + } + + public function cancelEdit(): void + { + $this->editingLineId = null; + $this->resetForm(); + } + + public function deleteLine(int $lineId): void + { + if ($this->invoice->isLocked()) { + return; + } + + $line = $this->invoice->lines()->find($lineId); + $line?->delete(); + $this->invoice->refresh(); + $this->dispatch('lines-updated'); + } + + private function resetForm(): void + { + $this->product_id = null; + $this->sku = null; + $this->name = ''; + $this->description = null; + $this->school_year = $this->defaultSchoolYear(); + $this->quantity = 1; + $this->unit_price = 0; + } +}; +?> + +