From 33f66a561ea45b1262028ac50157b73458883250 Mon Sep 17 00:00:00 2001 From: Nisse Lommerde Date: Tue, 21 Jan 2025 21:28:41 -0500 Subject: [PATCH] Work on customer login --- .../Admin/Resources/InvoiceResource.php | 34 +++++++++++++++---- app/Filament/Admin/Resources/UserResource.php | 8 ++++- app/Models/Customer.php | 6 ++++ app/Models/Invoice.php | 13 +++++-- app/Models/User.php | 7 ++++ app/Observers/InvoiceObserver.php | 1 + database/factories/InvoiceFactory.php | 6 ++-- .../migrations/000_create_users_table.php | 1 + .../migrations/007_create_invoices_table.php | 3 ++ database/seeders/TaxRateSeeder.php | 1 + tests/Unit/InvoiceTest.php | 4 +++ 11 files changed, 72 insertions(+), 12 deletions(-) diff --git a/app/Filament/Admin/Resources/InvoiceResource.php b/app/Filament/Admin/Resources/InvoiceResource.php index a66b951..766b146 100644 --- a/app/Filament/Admin/Resources/InvoiceResource.php +++ b/app/Filament/Admin/Resources/InvoiceResource.php @@ -90,6 +90,16 @@ public static function form(Form $form): Form 'true' => 'info', 'false' => 'info', ]), + + ToggleButtons::make('has_hst') + ->label('HST') + ->boolean('On', 'Off') + ->default(false) + ->inline() + ->colors([ + 'true' => 'info', + 'false' => 'info', + ]), ])->columnSpan(1), ]) ->columns(3) @@ -101,16 +111,16 @@ public static function form(Form $form): Form ->label('ID') ->content(fn (Invoice $record): ?string => $record->internal_id), - Placeholder::make('Tax Rates') - ->content(fn (Invoice $record): ?string => $record->gst_rate.'% GST, '.$record->pst_rate.'% PST'), + Placeholder::make('Tax Rates '.'(if applicable)') + ->content(fn (Invoice $record): ?string => $record->gst_rate.'% GST, '.$record->pst_rate.'% PST, '.$record->hst_rate.'% HST'), Placeholder::make('created_at') ->label('Created') - ->content(fn (Invoice $record): ?string => $record->created_at?->diffForHumans()), + ->content(fn (Invoice $record): ?string => $record->created_at->format('Y-m-d')), Placeholder::make('updated_at') ->label('Last modified') - ->content(fn (Invoice $record): ?string => $record->updated_at?->diffForHumans()), + ->content(fn (Invoice $record): ?string => $record->updated_at->format('Y-m-d')), ]) ->columnSpan(1) @@ -156,9 +166,10 @@ public static function table(Table $table): Table TextColumn::make('has_gst') ->label('GST') + ->money() ->formatStateUsing(function (Invoice $record) { if ($record->has_gst) { - return '$'.$record->gst_amount; + return '$'.number_format($record->gst_amount, 2); } return '-'; @@ -169,7 +180,18 @@ public static function table(Table $table): Table ->label('PST') ->formatStateUsing(function (Invoice $record) { if ($record->has_pst) { - return '$'.$record->pst_amount; + return '$'.number_format($record->pst_amount, 2); + } + + return '-'; + }) + ->alignRight(), + TextColumn::make('has_hst') + ->label('HST') + ->money() + ->formatStateUsing(function (Invoice $record) { + if ($record->has_hst) { + return '$'.number_format($record->hst_amount, 2); } return '-'; diff --git a/app/Filament/Admin/Resources/UserResource.php b/app/Filament/Admin/Resources/UserResource.php index 0b5f193..6ae35a4 100644 --- a/app/Filament/Admin/Resources/UserResource.php +++ b/app/Filament/Admin/Resources/UserResource.php @@ -6,6 +6,7 @@ use App\Models\User; use Filament\Forms\Components\Checkbox; use Filament\Forms\Components\Section; +use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; @@ -48,7 +49,12 @@ public static function form(Form $form): Form ->required(fn (string $operation) => $operation === 'create'), Checkbox::make('is_admin') - ->disabled(fn (User $record) => auth()->user()->id === $record->id), + ->disabled(fn (?User $record, $operation) => $operation !== 'create' && auth()->user()->id === $record->id), + + Select::make('customer_id') + ->relationship('customer', 'company_name') + ->searchable() + ->preload(), ]), ]); } diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 9cea0a7..c48123f 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\SoftDeletes; class Customer extends Model @@ -100,4 +101,9 @@ public function invoices(): HasMany { return $this->hasMany(Invoice::class); } + + public function user(): HasOne + { + return $this->hasOne(User::class); + } } diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index df485d2..1e77b7d 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -12,7 +12,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Support\Facades\Log; #[ObservedBy(InvoiceObserver::class)] @@ -31,10 +30,13 @@ class Invoice extends Model 'total', 'pst_rate', 'gst_rate', + 'hst_rate', 'pst_amount', 'gst_amount', + 'hst_amount', 'has_pst', 'has_gst', + 'has_hst', 'date', 'due_date', ]; @@ -42,11 +44,13 @@ class Invoice extends Model protected $casts = [ 'has_gst' => 'boolean', 'has_pst' => 'boolean', + 'has_hst' => 'boolean', 'date' => 'datetime', 'status' => InvoiceStatus::class, 'subtotal' => 'float', 'pst_amount' => 'float', 'gst_amount' => 'float', + 'hst_amount' => 'float', 'total' => 'float', ]; @@ -60,23 +64,26 @@ public function calculateTotals(): void $this->subtotal = 0; $this->gst_amount = 0; $this->pst_amount = 0; + $this->hst_amount = 0; $this->total = 0; return; } $subtotal = $this->orders->sum(fn (Order $order) => $order->total_service_price); - Log::debug('subtotal: '.$subtotal); $this->subtotal = $subtotal; $this->saveQuietly(); $gstAmount = $this->calculateTaxAmount($subtotal, $this->gst_rate, $this->has_gst); $pstAmount = $this->calculateTaxAmount($subtotal, $this->pst_rate, $this->has_pst); + $hstAmount = $this->calculateTaxAmount($subtotal, $this->hst_rate, $this->has_hst); $this->gst_amount = $gstAmount; $this->pst_amount = $pstAmount; - $this->total = $subtotal + $gstAmount + $pstAmount; + $this->hst_amount = $hstAmount; + + $this->total = $subtotal + $gstAmount + $pstAmount + $hstAmount; $this->saveQuietly(); } diff --git a/app/Models/User.php b/app/Models/User.php index d45a35b..dc5483a 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -5,6 +5,7 @@ use Database\Factories\UserFactory; use Filament\Models\Contracts\HasName; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; @@ -22,6 +23,7 @@ class User extends Authenticatable implements HasName 'username', 'is_admin', 'password', + 'customer_id', ]; /** @@ -50,4 +52,9 @@ public function getFilamentName(): string { return $this->username; } + + public function customer(): BelongsTo + { + return $this->belongsTo(Customer::class); + } } diff --git a/app/Observers/InvoiceObserver.php b/app/Observers/InvoiceObserver.php index e4078cb..339a909 100644 --- a/app/Observers/InvoiceObserver.php +++ b/app/Observers/InvoiceObserver.php @@ -14,6 +14,7 @@ public function creating(Invoice $invoice): void { $invoice->pst_rate = TaxRate::where('name', 'PST')->value('value') ?? 0; $invoice->gst_rate = TaxRate::where('name', 'GST')->value('value') ?? 0; + $invoice->hst_rate = TaxRate::where('name', 'HST')->value('value') ?? 0; } /** diff --git a/database/factories/InvoiceFactory.php b/database/factories/InvoiceFactory.php index 341cbfa..f02dadd 100644 --- a/database/factories/InvoiceFactory.php +++ b/database/factories/InvoiceFactory.php @@ -19,10 +19,12 @@ public function definition(): array return [ 'created_at' => Carbon::now()->subDays(rand(1, 30)), - 'pst_rate' => TaxRate::where('name', 'PST')->value('value'), - 'gst_rate' => TaxRate::where('name', 'GST')->value('value'), + 'pst_rate' => TaxRate::where('name', 'PST')->value('value') ?? 0, + 'gst_rate' => TaxRate::where('name', 'GST')->value('value') ?? 0, + 'hst_rate' => TaxRate::where('name', 'HST')->value('value') ?? 0, 'has_gst' => true, 'has_pst' => $this->faker->boolean(40), + 'has_hst' => false, 'date' => Carbon::now()->subDays(rand(1, 60)), 'status' => $this->faker->randomElement(InvoiceStatus::cases())->value, 'customer_id' => $customer->id, diff --git a/database/migrations/000_create_users_table.php b/database/migrations/000_create_users_table.php index 7043251..8ab5211 100644 --- a/database/migrations/000_create_users_table.php +++ b/database/migrations/000_create_users_table.php @@ -13,6 +13,7 @@ public function up(): void { Schema::create('users', function (Blueprint $table) { $table->id(); + $table->foreignId('customer_id')->nullable()->constrained(); $table->string('username')->unique(); $table->string('password'); $table->boolean('is_admin')->default(0); diff --git a/database/migrations/007_create_invoices_table.php b/database/migrations/007_create_invoices_table.php index 3fce718..1c3bc04 100644 --- a/database/migrations/007_create_invoices_table.php +++ b/database/migrations/007_create_invoices_table.php @@ -21,12 +21,15 @@ public function up(): void $table->decimal('pst_rate', 8, 2); $table->decimal('gst_rate', 8, 2); + $table->decimal('hst_rate', 8, 2); $table->decimal('pst_amount', 8, 2)->nullable(); $table->decimal('gst_amount', 8, 2)->nullable(); + $table->decimal('hst_amount', 8, 2)->nullable(); $table->boolean('has_pst')->default(false); $table->boolean('has_gst')->default(true); + $table->boolean('has_hst')->default(false); $table->date('date')->default(today()); $table->date('due_date')->nullable(); diff --git a/database/seeders/TaxRateSeeder.php b/database/seeders/TaxRateSeeder.php index 639cd03..0b9180a 100644 --- a/database/seeders/TaxRateSeeder.php +++ b/database/seeders/TaxRateSeeder.php @@ -14,5 +14,6 @@ public function run(): void { TaxRate::create(['name' => 'GST', 'value' => 5.00]); TaxRate::create(['name' => 'PST', 'value' => 7.00]); + TaxRate::create(['name' => 'HST', 'value' => 13.00]); } } diff --git a/tests/Unit/InvoiceTest.php b/tests/Unit/InvoiceTest.php index 9e3f806..0bdd36c 100644 --- a/tests/Unit/InvoiceTest.php +++ b/tests/Unit/InvoiceTest.php @@ -19,6 +19,7 @@ $customer = Customer::factory()->create(); // Generates a customer $pst_rate = TaxRate::where('name', 'PST')->value('value') ?? 0; $gst_rate = TaxRate::where('name', 'GST')->value('value') ?? 0; + $hst_rate = TaxRate::where('name', 'HST')->value('value') ?? 0; $formData = [ 'customer_id' => $customer->id, @@ -27,6 +28,7 @@ 'status' => InvoiceStatus::UNPAID->value, 'has_gst' => true, 'has_pst' => true, + 'has_hst' => false, ]; $this->livewire(CreateInvoice::class) @@ -40,8 +42,10 @@ 'status' => $formData['status'], 'has_gst' => $formData['has_gst'], 'has_pst' => $formData['has_pst'], + 'has_hst' => $formData['has_hst'], 'gst_rate' => $gst_rate, 'pst_rate' => $pst_rate, + 'hst_rate' => $hst_rate, ]); $invoice = Invoice::where('internal_id', 'INV400001')->firstOrFail();