Work on customer login
This commit is contained in:
parent
b320915fc1
commit
f937302159
@ -2,8 +2,12 @@
|
||||
|
||||
namespace App\Filament\Admin\Pages;
|
||||
|
||||
use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
|
||||
use Filament\Facades\Filament;
|
||||
use Filament\Forms\Components\Component;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Http\Responses\Auth\Contracts\LoginResponse;
|
||||
use Filament\Models\Contracts\FilamentUser;
|
||||
use Filament\Pages\Auth\Login;
|
||||
use Illuminate\Contracts\Support\Htmlable;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
@ -28,6 +32,41 @@ protected function getCredentialsFromFormData(array $data): array
|
||||
];
|
||||
}
|
||||
|
||||
public function authenticate(): ?LoginResponse
|
||||
{
|
||||
try {
|
||||
$this->rateLimit(5);
|
||||
} catch (TooManyRequestsException $exception) {
|
||||
$this->getRateLimitedNotification($exception)?->send();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = $this->form->getState();
|
||||
|
||||
if (! Filament::auth()->attempt($this->getCredentialsFromFormData($data), $data['remember'] ?? false)) {
|
||||
$this->throwFailureValidationException();
|
||||
}
|
||||
|
||||
$user = Filament::auth()->user();
|
||||
|
||||
if (($user instanceof FilamentUser) && (! $user->canAccessPanel(Filament::getCurrentPanel()))) {
|
||||
Filament::auth()->logout();
|
||||
|
||||
$this->throwFailureValidationException();
|
||||
} elseif ($user->customer_id !== null) {
|
||||
Filament::auth()->logout();
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'data.username' => 'Incorrect username or password.',
|
||||
]);
|
||||
}
|
||||
|
||||
session()->regenerate();
|
||||
|
||||
return app(LoginResponse::class);
|
||||
}
|
||||
|
||||
protected function throwFailureValidationException(): never
|
||||
{
|
||||
throw ValidationException::withMessages([
|
||||
|
@ -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 '-';
|
||||
|
@ -121,7 +121,7 @@ public static function form(Form $form): Form
|
||||
|
||||
])->columnSpan(1),
|
||||
])->columns(2)
|
||||
->columnSpan(fn (?Order $record) => $record === null ? 4 : 3),
|
||||
->columnSpan(fn (?Order $record) => $record === null ? 6 : 5),
|
||||
|
||||
Section::make()
|
||||
->schema([
|
||||
@ -140,7 +140,7 @@ public static function form(Form $form): Form
|
||||
->columnSpan(1)
|
||||
->hidden(fn (?Order $record) => $record === null),
|
||||
])
|
||||
->columns(4)
|
||||
->columns(6)
|
||||
->columnSpan(2),
|
||||
|
||||
TableRepeater::make('order_products')
|
||||
@ -174,7 +174,8 @@ public static function form(Form $form): Form
|
||||
->label('Sizes'),
|
||||
])
|
||||
->reorderable()
|
||||
->cloneable(),
|
||||
->cloneable()
|
||||
->defaultItems(1),
|
||||
|
||||
Repeater::make('services')
|
||||
->label('Product Services')
|
||||
@ -246,7 +247,8 @@ public static function form(Form $form): Form
|
||||
->reorderable()
|
||||
->cloneable()
|
||||
->columns(4)
|
||||
->columnSpan(2),
|
||||
->columnSpan(2)
|
||||
->defaultItems(1),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -168,6 +168,30 @@ protected function getHeaderActions(): array
|
||||
$replica->order_date = today();
|
||||
$replica->due_date = today()->addDays(10);
|
||||
$replica->save();
|
||||
|
||||
foreach ($this->record->orderProducts as $product) {
|
||||
$newProduct = $product->replicate();
|
||||
$newProduct->order_id = $replica->id;
|
||||
$newProduct->save();
|
||||
|
||||
foreach ($product->productSizes as $size) {
|
||||
$newSize = $size->replicate();
|
||||
$newSize->order_product_id = $newProduct->id;
|
||||
$newSize->save();
|
||||
}
|
||||
}
|
||||
|
||||
/** @var ProductService $service */
|
||||
foreach ($this->record->productServices as $service) {
|
||||
/** @var ServiceFile $newServiceFile */
|
||||
$newServiceFile = $service->serviceFile->replicate();
|
||||
|
||||
$newService = $service->replicate();
|
||||
$newService->order_id = $replica->id;
|
||||
$newService->service_file_id = $newServiceFile->id;
|
||||
|
||||
$newService->save();
|
||||
}
|
||||
})
|
||||
->successRedirectUrl(fn (Model $replica): string => OrderResource::getUrl('edit', [$replica])),
|
||||
|
||||
|
@ -7,10 +7,11 @@
|
||||
use App\Models\Order;
|
||||
use App\Models\PackingSlip;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\Grid;
|
||||
use Filament\Forms\Components\Section;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\Split;
|
||||
use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
@ -32,28 +33,36 @@ public static function form(Form $form): Form
|
||||
return $form
|
||||
->schema([
|
||||
Section::make([
|
||||
DatePicker::make('date_received')
|
||||
->default(today())
|
||||
->required(),
|
||||
// TextInput::make('amount')
|
||||
// ->label('Quantity')
|
||||
// ->required(),
|
||||
Select::make('customer_id')
|
||||
->label('Customer')
|
||||
->options(Customer::all()->pluck('company_name', 'id'))
|
||||
->reactive()
|
||||
->searchable(),
|
||||
Select::make('order_id')
|
||||
->label('Order')
|
||||
->required()
|
||||
->options(fn ($get): array => Order::where('customer_id', $get('customer_id') ?? null)
|
||||
->get()
|
||||
->pluck('customer_po', 'id')
|
||||
->toArray())
|
||||
->searchable(),
|
||||
TextArea::make('contents'),
|
||||
])
|
||||
->columns(2),
|
||||
Split::make([
|
||||
Grid::make(1)
|
||||
->schema([
|
||||
DatePicker::make('date_received')
|
||||
->default(today())
|
||||
->required(),
|
||||
Select::make('customer_id')
|
||||
->label('Customer')
|
||||
->options(Customer::all()->pluck('company_name', 'id'))
|
||||
->reactive()
|
||||
->searchable(),
|
||||
Select::make('order_id')
|
||||
->label('Order')
|
||||
->required()
|
||||
->options(fn ($get): array => Order::where('customer_id', $get('customer_id') ?? null)
|
||||
->get()
|
||||
->pluck('customer_po', 'id')
|
||||
->toArray())
|
||||
->searchable(),
|
||||
])
|
||||
->columnSpan(1),
|
||||
|
||||
Grid::make(1)
|
||||
->schema([
|
||||
TextArea::make('contents')
|
||||
->rows(9),
|
||||
])
|
||||
->columnSpan(1),
|
||||
]),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -65,6 +74,8 @@ public static function table(Table $table): Table
|
||||
->sortable()
|
||||
->searchable(),
|
||||
TextColumn::make('order.customer_po')
|
||||
// ->url(fn ($record) => $record->to)
|
||||
->url(fn ($record) => OrderResource::getUrl('edit', ['record' => $record->id]))
|
||||
->weight('bold')
|
||||
->color('code')
|
||||
->sortable()
|
||||
|
@ -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;
|
||||
@ -31,6 +32,7 @@ public static function form(Form $form): Form
|
||||
->schema([
|
||||
TextInput::make('username')
|
||||
->autocomplete(false)
|
||||
->unique()
|
||||
->required(),
|
||||
|
||||
TextInput::make('password')
|
||||
@ -48,7 +50,18 @@ 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),
|
||||
->label('Admin')
|
||||
->reactive()
|
||||
->afterStateUpdated(fn ($state, callable $set) => $set('customer_id', null))
|
||||
->disabled(fn (?User $record, $operation) => $operation !== 'create' && auth()->user()->id === $record->id),
|
||||
|
||||
Select::make('customer_id')
|
||||
->relationship('customer', 'company_name')
|
||||
->disabled(fn ($get) => $get('is_admin'))
|
||||
->afterStateUpdated(fn ($state, callable $set) => $set('is_admin', false))
|
||||
->nullable()
|
||||
->searchable()
|
||||
->preload(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
@ -59,6 +72,8 @@ public static function table(Table $table): Table
|
||||
->columns([
|
||||
TextColumn::make('username')
|
||||
->extraHeaderAttributes(['class' => 'w-full']),
|
||||
TextColumn::make('customer.company_name')
|
||||
->sortable(),
|
||||
Tables\Columns\IconColumn::make('is_admin')
|
||||
->label('Admin')
|
||||
->boolean()
|
||||
@ -70,11 +85,7 @@ public static function table(Table $table): Table
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
->defaultSort('customer_id', 'asc');
|
||||
}
|
||||
|
||||
public static function canAccess(): bool
|
||||
|
87
app/Filament/Customer/Pages/CustomerLogin.php
Normal file
87
app/Filament/Customer/Pages/CustomerLogin.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Customer\Pages;
|
||||
|
||||
use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
|
||||
use Filament\Facades\Filament;
|
||||
use Filament\Forms\Components\Component;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Http\Responses\Auth\Contracts\LoginResponse;
|
||||
use Filament\Models\Contracts\FilamentUser;
|
||||
use Filament\Pages\Auth\Login;
|
||||
use Illuminate\Contracts\Support\Htmlable;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CustomerLogin extends Login
|
||||
{
|
||||
protected function getEmailFormComponent(): Component
|
||||
{
|
||||
return TextInput::make('username')
|
||||
->label('Username')
|
||||
->required()
|
||||
->autofocus()
|
||||
->extraInputAttributes(['tabindex' => 1])
|
||||
->autocomplete();
|
||||
}
|
||||
|
||||
protected function getCredentialsFromFormData(array $data): array
|
||||
{
|
||||
return [
|
||||
'username' => $data['username'],
|
||||
'password' => $data['password'],
|
||||
];
|
||||
}
|
||||
|
||||
protected function throwFailureValidationException(): never
|
||||
{
|
||||
throw ValidationException::withMessages([
|
||||
'data.username' => __('filament-panels::pages/auth/login.messages.failed'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function authenticate(): ?LoginResponse
|
||||
{
|
||||
try {
|
||||
$this->rateLimit(5);
|
||||
} catch (TooManyRequestsException $exception) {
|
||||
$this->getRateLimitedNotification($exception)?->send();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = $this->form->getState();
|
||||
|
||||
if (! Filament::auth()->attempt($this->getCredentialsFromFormData($data), $data['remember'] ?? false)) {
|
||||
$this->throwFailureValidationException();
|
||||
}
|
||||
|
||||
$user = Filament::auth()->user();
|
||||
|
||||
if (($user instanceof FilamentUser) && (! $user->canAccessPanel(Filament::getCurrentPanel()))) {
|
||||
Filament::auth()->logout();
|
||||
|
||||
$this->throwFailureValidationException();
|
||||
} elseif ($user->customer_id === null) {
|
||||
Filament::auth()->logout();
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'data.username' => 'Incorrect username or password.',
|
||||
]);
|
||||
}
|
||||
|
||||
session()->regenerate();
|
||||
|
||||
return app(LoginResponse::class);
|
||||
}
|
||||
|
||||
public function getTitle(): Htmlable|string
|
||||
{
|
||||
return __('Login');
|
||||
|
||||
}
|
||||
|
||||
public function getHeading(): Htmlable|string
|
||||
{
|
||||
return __('Login');
|
||||
}
|
||||
}
|
@ -5,9 +5,10 @@
|
||||
use App\Enums\IconEnum;
|
||||
use App\Filament\Customer\Resources\OrderResource\Pages;
|
||||
use App\Models\Order;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Infolists\Components\TextEntry;
|
||||
use Filament\Infolists\Infolist;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Actions\ViewAction;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
@ -17,11 +18,15 @@ class OrderResource extends Resource
|
||||
|
||||
protected static ?string $navigationIcon = IconEnum::ORDER->value;
|
||||
|
||||
public static function form(Form $form): Form
|
||||
public static function infolist(Infolist $infolist): Infolist
|
||||
{
|
||||
return $form
|
||||
return $infolist
|
||||
->schema([
|
||||
//
|
||||
TextEntry::make('internal_po'),
|
||||
TextEntry::make('customer_po'),
|
||||
TextEntry::make('order_date'),
|
||||
TextEntry::make('due_date'),
|
||||
TextEntry::make('status'),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -29,25 +34,12 @@ public static function table(Table $table): Table
|
||||
{
|
||||
return \App\Filament\Admin\Resources\OrderResource::table($table)
|
||||
->modifyQueryUsing(function (Builder $query) {
|
||||
return $query->where('customer_id', 1);
|
||||
return $query->where('customer_id', auth()->user()->customer_id);
|
||||
})
|
||||
->actions([])
|
||||
->actions([
|
||||
ViewAction::make(),
|
||||
])
|
||||
->bulKActions([]);
|
||||
// $table
|
||||
// ->columns([
|
||||
// //
|
||||
// ])
|
||||
// ->filters([
|
||||
// //
|
||||
// ])
|
||||
// ->actions([
|
||||
// Tables\Actions\EditAction::make(),
|
||||
// ])
|
||||
// ->bulkActions([
|
||||
// Tables\Actions\BulkActionGroup::make([
|
||||
// Tables\Actions\DeleteBulkAction::make(),
|
||||
// ]),
|
||||
// ]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
@ -61,8 +53,6 @@ public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListOrders::route('/'),
|
||||
// 'create' => Pages\CreateOrder::route('/create'),
|
||||
// 'edit' => Pages\EditOrder::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Customer\Resources\OrderResource\Pages;
|
||||
|
||||
use App\Filament\Customer\Resources\OrderResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateOrder extends CreateRecord
|
||||
{
|
||||
protected static string $resource = OrderResource::class;
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Customer\Resources\OrderResource\Pages;
|
||||
|
||||
use App\Filament\Customer\Resources\OrderResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditOrder extends EditRecord
|
||||
{
|
||||
protected static string $resource = OrderResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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',
|
||||
];
|
||||
|
||||
/**
|
||||
@ -46,8 +48,34 @@ protected function casts(): array
|
||||
];
|
||||
}
|
||||
|
||||
public function setIsAdminAttribute(bool $value): void
|
||||
{
|
||||
$this->attributes['is_admin'] = $value;
|
||||
$this->ensureCustomerIsNotAdmin();
|
||||
}
|
||||
|
||||
public function setCustomerIdAttribute(?int $value): void
|
||||
{
|
||||
$this->attributes['customer_id'] = $value;
|
||||
$this->ensureCustomerIsNotAdmin();
|
||||
}
|
||||
|
||||
public function ensureCustomerIsNotAdmin(): void
|
||||
{
|
||||
if ($this->is_admin) {
|
||||
$this->customer_id = null;
|
||||
} elseif ($this->customer_id) {
|
||||
$this->is_admin = false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getFilamentName(): string
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function customer(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Customer::class);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Providers\Filament;
|
||||
|
||||
use App\Filament\Customer\Pages\CustomerLogin;
|
||||
use Filament\Http\Middleware\Authenticate;
|
||||
use Filament\Http\Middleware\DisableBladeIconComponents;
|
||||
use Filament\Http\Middleware\DispatchServingFilamentEvent;
|
||||
@ -9,7 +10,6 @@
|
||||
use Filament\Panel;
|
||||
use Filament\PanelProvider;
|
||||
use Filament\Support\Colors\Color;
|
||||
use Filament\Widgets;
|
||||
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
||||
use Illuminate\Cookie\Middleware\EncryptCookies;
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
|
||||
@ -35,11 +35,9 @@ public function panel(Panel $panel): Panel
|
||||
// ->pages([
|
||||
// Pages\Dashboard::class,
|
||||
// ])
|
||||
->login(CustomerLogin::class)
|
||||
->discoverWidgets(in: app_path('Filament/Customer/Widgets'), for: 'App\\Filament\\Customer\\Widgets')
|
||||
->widgets([
|
||||
Widgets\AccountWidget::class,
|
||||
Widgets\FilamentInfoWidget::class,
|
||||
])
|
||||
->widgets([])
|
||||
->middleware([
|
||||
EncryptCookies::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
@ -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();
|
||||
|
@ -17,6 +17,7 @@ public function run(): void
|
||||
$this->call([
|
||||
TaxRateSeeder::class,
|
||||
CustomerSeeder::class,
|
||||
UserSeeder::class,
|
||||
ContactSeeder::class,
|
||||
ShippingEntrySeeder::class,
|
||||
OrderSeeder::class,
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
24
database/seeders/UserSeeder.php
Normal file
24
database/seeders/UserSeeder.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Customer;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class UserSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
foreach (Customer::all() as $customer) {
|
||||
User::factory([
|
||||
'username' => str_replace(',', '', strtolower(explode(' ', $customer->company_name)[0])),
|
||||
'password' => 'password',
|
||||
'customer_id' => $customer->id,
|
||||
])->create();
|
||||
}
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@
|
||||
{{
|
||||
$attributes
|
||||
->merge($getExtraAttributes(), escape: false)
|
||||
->class(['bg-white border border-gray-150 rounded-xl relative dark:bg-gray-900 dark:border-gray-700'])
|
||||
->class(['bg-white border border-gray-150 rounded-xl relative dark:bg-gray-900 dark:border-gray-700'])
|
||||
}}
|
||||
>
|
||||
|
||||
@ -183,12 +183,13 @@ class="flex items-center justify-center"
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($isAddable)
|
||||
<div class="relative flex justify-center py-2">
|
||||
{{ $addAction }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
@if($isAddable)
|
||||
<div class="relative flex justify-center py-2">
|
||||
{{ $addAction }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</x-dynamic-component>
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user