Work on customer login
This commit is contained in:
parent
b320915fc1
commit
f937302159
@ -2,8 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Filament\Admin\Pages;
|
namespace App\Filament\Admin\Pages;
|
||||||
|
|
||||||
|
use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
|
||||||
|
use Filament\Facades\Filament;
|
||||||
use Filament\Forms\Components\Component;
|
use Filament\Forms\Components\Component;
|
||||||
use Filament\Forms\Components\TextInput;
|
use Filament\Forms\Components\TextInput;
|
||||||
|
use Filament\Http\Responses\Auth\Contracts\LoginResponse;
|
||||||
|
use Filament\Models\Contracts\FilamentUser;
|
||||||
use Filament\Pages\Auth\Login;
|
use Filament\Pages\Auth\Login;
|
||||||
use Illuminate\Contracts\Support\Htmlable;
|
use Illuminate\Contracts\Support\Htmlable;
|
||||||
use Illuminate\Validation\ValidationException;
|
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
|
protected function throwFailureValidationException(): never
|
||||||
{
|
{
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
|
@ -90,6 +90,16 @@ public static function form(Form $form): Form
|
|||||||
'true' => 'info',
|
'true' => 'info',
|
||||||
'false' => 'info',
|
'false' => 'info',
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
ToggleButtons::make('has_hst')
|
||||||
|
->label('HST')
|
||||||
|
->boolean('On', 'Off')
|
||||||
|
->default(false)
|
||||||
|
->inline()
|
||||||
|
->colors([
|
||||||
|
'true' => 'info',
|
||||||
|
'false' => 'info',
|
||||||
|
]),
|
||||||
])->columnSpan(1),
|
])->columnSpan(1),
|
||||||
])
|
])
|
||||||
->columns(3)
|
->columns(3)
|
||||||
@ -101,16 +111,16 @@ public static function form(Form $form): Form
|
|||||||
->label('ID')
|
->label('ID')
|
||||||
->content(fn (Invoice $record): ?string => $record->internal_id),
|
->content(fn (Invoice $record): ?string => $record->internal_id),
|
||||||
|
|
||||||
Placeholder::make('Tax Rates')
|
Placeholder::make('Tax Rates '.'(if applicable)')
|
||||||
->content(fn (Invoice $record): ?string => $record->gst_rate.'% GST, '.$record->pst_rate.'% PST'),
|
->content(fn (Invoice $record): ?string => $record->gst_rate.'% GST, '.$record->pst_rate.'% PST, '.$record->hst_rate.'% HST'),
|
||||||
|
|
||||||
Placeholder::make('created_at')
|
Placeholder::make('created_at')
|
||||||
->label('Created')
|
->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')
|
Placeholder::make('updated_at')
|
||||||
->label('Last modified')
|
->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)
|
->columnSpan(1)
|
||||||
@ -156,9 +166,10 @@ public static function table(Table $table): Table
|
|||||||
|
|
||||||
TextColumn::make('has_gst')
|
TextColumn::make('has_gst')
|
||||||
->label('GST')
|
->label('GST')
|
||||||
|
->money()
|
||||||
->formatStateUsing(function (Invoice $record) {
|
->formatStateUsing(function (Invoice $record) {
|
||||||
if ($record->has_gst) {
|
if ($record->has_gst) {
|
||||||
return '$'.$record->gst_amount;
|
return '$'.number_format($record->gst_amount, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return '-';
|
return '-';
|
||||||
@ -169,7 +180,18 @@ public static function table(Table $table): Table
|
|||||||
->label('PST')
|
->label('PST')
|
||||||
->formatStateUsing(function (Invoice $record) {
|
->formatStateUsing(function (Invoice $record) {
|
||||||
if ($record->has_pst) {
|
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 '-';
|
return '-';
|
||||||
|
@ -121,7 +121,7 @@ public static function form(Form $form): Form
|
|||||||
|
|
||||||
])->columnSpan(1),
|
])->columnSpan(1),
|
||||||
])->columns(2)
|
])->columns(2)
|
||||||
->columnSpan(fn (?Order $record) => $record === null ? 4 : 3),
|
->columnSpan(fn (?Order $record) => $record === null ? 6 : 5),
|
||||||
|
|
||||||
Section::make()
|
Section::make()
|
||||||
->schema([
|
->schema([
|
||||||
@ -140,7 +140,7 @@ public static function form(Form $form): Form
|
|||||||
->columnSpan(1)
|
->columnSpan(1)
|
||||||
->hidden(fn (?Order $record) => $record === null),
|
->hidden(fn (?Order $record) => $record === null),
|
||||||
])
|
])
|
||||||
->columns(4)
|
->columns(6)
|
||||||
->columnSpan(2),
|
->columnSpan(2),
|
||||||
|
|
||||||
TableRepeater::make('order_products')
|
TableRepeater::make('order_products')
|
||||||
@ -174,7 +174,8 @@ public static function form(Form $form): Form
|
|||||||
->label('Sizes'),
|
->label('Sizes'),
|
||||||
])
|
])
|
||||||
->reorderable()
|
->reorderable()
|
||||||
->cloneable(),
|
->cloneable()
|
||||||
|
->defaultItems(1),
|
||||||
|
|
||||||
Repeater::make('services')
|
Repeater::make('services')
|
||||||
->label('Product Services')
|
->label('Product Services')
|
||||||
@ -246,7 +247,8 @@ public static function form(Form $form): Form
|
|||||||
->reorderable()
|
->reorderable()
|
||||||
->cloneable()
|
->cloneable()
|
||||||
->columns(4)
|
->columns(4)
|
||||||
->columnSpan(2),
|
->columnSpan(2)
|
||||||
|
->defaultItems(1),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +168,30 @@ protected function getHeaderActions(): array
|
|||||||
$replica->order_date = today();
|
$replica->order_date = today();
|
||||||
$replica->due_date = today()->addDays(10);
|
$replica->due_date = today()->addDays(10);
|
||||||
$replica->save();
|
$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])),
|
->successRedirectUrl(fn (Model $replica): string => OrderResource::getUrl('edit', [$replica])),
|
||||||
|
|
||||||
|
@ -7,10 +7,11 @@
|
|||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
use App\Models\PackingSlip;
|
use App\Models\PackingSlip;
|
||||||
use Filament\Forms\Components\DatePicker;
|
use Filament\Forms\Components\DatePicker;
|
||||||
|
use Filament\Forms\Components\Grid;
|
||||||
use Filament\Forms\Components\Section;
|
use Filament\Forms\Components\Section;
|
||||||
use Filament\Forms\Components\Select;
|
use Filament\Forms\Components\Select;
|
||||||
|
use Filament\Forms\Components\Split;
|
||||||
use Filament\Forms\Components\Textarea;
|
use Filament\Forms\Components\Textarea;
|
||||||
use Filament\Forms\Components\TextInput;
|
|
||||||
use Filament\Forms\Form;
|
use Filament\Forms\Form;
|
||||||
use Filament\Resources\Resource;
|
use Filament\Resources\Resource;
|
||||||
use Filament\Tables;
|
use Filament\Tables;
|
||||||
@ -32,28 +33,36 @@ public static function form(Form $form): Form
|
|||||||
return $form
|
return $form
|
||||||
->schema([
|
->schema([
|
||||||
Section::make([
|
Section::make([
|
||||||
DatePicker::make('date_received')
|
Split::make([
|
||||||
->default(today())
|
Grid::make(1)
|
||||||
->required(),
|
->schema([
|
||||||
// TextInput::make('amount')
|
DatePicker::make('date_received')
|
||||||
// ->label('Quantity')
|
->default(today())
|
||||||
// ->required(),
|
->required(),
|
||||||
Select::make('customer_id')
|
Select::make('customer_id')
|
||||||
->label('Customer')
|
->label('Customer')
|
||||||
->options(Customer::all()->pluck('company_name', 'id'))
|
->options(Customer::all()->pluck('company_name', 'id'))
|
||||||
->reactive()
|
->reactive()
|
||||||
->searchable(),
|
->searchable(),
|
||||||
Select::make('order_id')
|
Select::make('order_id')
|
||||||
->label('Order')
|
->label('Order')
|
||||||
->required()
|
->required()
|
||||||
->options(fn ($get): array => Order::where('customer_id', $get('customer_id') ?? null)
|
->options(fn ($get): array => Order::where('customer_id', $get('customer_id') ?? null)
|
||||||
->get()
|
->get()
|
||||||
->pluck('customer_po', 'id')
|
->pluck('customer_po', 'id')
|
||||||
->toArray())
|
->toArray())
|
||||||
->searchable(),
|
->searchable(),
|
||||||
TextArea::make('contents'),
|
])
|
||||||
])
|
->columnSpan(1),
|
||||||
->columns(2),
|
|
||||||
|
Grid::make(1)
|
||||||
|
->schema([
|
||||||
|
TextArea::make('contents')
|
||||||
|
->rows(9),
|
||||||
|
])
|
||||||
|
->columnSpan(1),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +74,8 @@ public static function table(Table $table): Table
|
|||||||
->sortable()
|
->sortable()
|
||||||
->searchable(),
|
->searchable(),
|
||||||
TextColumn::make('order.customer_po')
|
TextColumn::make('order.customer_po')
|
||||||
|
// ->url(fn ($record) => $record->to)
|
||||||
|
->url(fn ($record) => OrderResource::getUrl('edit', ['record' => $record->id]))
|
||||||
->weight('bold')
|
->weight('bold')
|
||||||
->color('code')
|
->color('code')
|
||||||
->sortable()
|
->sortable()
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Filament\Forms\Components\Checkbox;
|
use Filament\Forms\Components\Checkbox;
|
||||||
use Filament\Forms\Components\Section;
|
use Filament\Forms\Components\Section;
|
||||||
|
use Filament\Forms\Components\Select;
|
||||||
use Filament\Forms\Components\TextInput;
|
use Filament\Forms\Components\TextInput;
|
||||||
use Filament\Forms\Form;
|
use Filament\Forms\Form;
|
||||||
use Filament\Resources\Resource;
|
use Filament\Resources\Resource;
|
||||||
@ -31,6 +32,7 @@ public static function form(Form $form): Form
|
|||||||
->schema([
|
->schema([
|
||||||
TextInput::make('username')
|
TextInput::make('username')
|
||||||
->autocomplete(false)
|
->autocomplete(false)
|
||||||
|
->unique()
|
||||||
->required(),
|
->required(),
|
||||||
|
|
||||||
TextInput::make('password')
|
TextInput::make('password')
|
||||||
@ -48,7 +50,18 @@ public static function form(Form $form): Form
|
|||||||
->required(fn (string $operation) => $operation === 'create'),
|
->required(fn (string $operation) => $operation === 'create'),
|
||||||
|
|
||||||
Checkbox::make('is_admin')
|
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([
|
->columns([
|
||||||
TextColumn::make('username')
|
TextColumn::make('username')
|
||||||
->extraHeaderAttributes(['class' => 'w-full']),
|
->extraHeaderAttributes(['class' => 'w-full']),
|
||||||
|
TextColumn::make('customer.company_name')
|
||||||
|
->sortable(),
|
||||||
Tables\Columns\IconColumn::make('is_admin')
|
Tables\Columns\IconColumn::make('is_admin')
|
||||||
->label('Admin')
|
->label('Admin')
|
||||||
->boolean()
|
->boolean()
|
||||||
@ -70,11 +85,7 @@ public static function table(Table $table): Table
|
|||||||
->actions([
|
->actions([
|
||||||
Tables\Actions\EditAction::make(),
|
Tables\Actions\EditAction::make(),
|
||||||
])
|
])
|
||||||
->bulkActions([
|
->defaultSort('customer_id', 'asc');
|
||||||
Tables\Actions\BulkActionGroup::make([
|
|
||||||
Tables\Actions\DeleteBulkAction::make(),
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function canAccess(): bool
|
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\Enums\IconEnum;
|
||||||
use App\Filament\Customer\Resources\OrderResource\Pages;
|
use App\Filament\Customer\Resources\OrderResource\Pages;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
use Filament\Forms\Form;
|
use Filament\Infolists\Components\TextEntry;
|
||||||
|
use Filament\Infolists\Infolist;
|
||||||
use Filament\Resources\Resource;
|
use Filament\Resources\Resource;
|
||||||
use Filament\Tables;
|
use Filament\Tables\Actions\ViewAction;
|
||||||
use Filament\Tables\Table;
|
use Filament\Tables\Table;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
@ -17,11 +18,15 @@ class OrderResource extends Resource
|
|||||||
|
|
||||||
protected static ?string $navigationIcon = IconEnum::ORDER->value;
|
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([
|
->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)
|
return \App\Filament\Admin\Resources\OrderResource::table($table)
|
||||||
->modifyQueryUsing(function (Builder $query) {
|
->modifyQueryUsing(function (Builder $query) {
|
||||||
return $query->where('customer_id', 1);
|
return $query->where('customer_id', auth()->user()->customer_id);
|
||||||
})
|
})
|
||||||
->actions([])
|
->actions([
|
||||||
|
ViewAction::make(),
|
||||||
|
])
|
||||||
->bulKActions([]);
|
->bulKActions([]);
|
||||||
// $table
|
|
||||||
// ->columns([
|
|
||||||
// //
|
|
||||||
// ])
|
|
||||||
// ->filters([
|
|
||||||
// //
|
|
||||||
// ])
|
|
||||||
// ->actions([
|
|
||||||
// Tables\Actions\EditAction::make(),
|
|
||||||
// ])
|
|
||||||
// ->bulkActions([
|
|
||||||
// Tables\Actions\BulkActionGroup::make([
|
|
||||||
// Tables\Actions\DeleteBulkAction::make(),
|
|
||||||
// ]),
|
|
||||||
// ]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getRelations(): array
|
public static function getRelations(): array
|
||||||
@ -61,8 +53,6 @@ public static function getPages(): array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'index' => Pages\ListOrders::route('/'),
|
'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\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
class Customer extends Model
|
class Customer extends Model
|
||||||
@ -100,4 +101,9 @@ public function invoices(): HasMany
|
|||||||
{
|
{
|
||||||
return $this->hasMany(Invoice::class);
|
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\HasMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
#[ObservedBy(InvoiceObserver::class)]
|
#[ObservedBy(InvoiceObserver::class)]
|
||||||
|
|
||||||
@ -31,10 +30,13 @@ class Invoice extends Model
|
|||||||
'total',
|
'total',
|
||||||
'pst_rate',
|
'pst_rate',
|
||||||
'gst_rate',
|
'gst_rate',
|
||||||
|
'hst_rate',
|
||||||
'pst_amount',
|
'pst_amount',
|
||||||
'gst_amount',
|
'gst_amount',
|
||||||
|
'hst_amount',
|
||||||
'has_pst',
|
'has_pst',
|
||||||
'has_gst',
|
'has_gst',
|
||||||
|
'has_hst',
|
||||||
'date',
|
'date',
|
||||||
'due_date',
|
'due_date',
|
||||||
];
|
];
|
||||||
@ -42,11 +44,13 @@ class Invoice extends Model
|
|||||||
protected $casts = [
|
protected $casts = [
|
||||||
'has_gst' => 'boolean',
|
'has_gst' => 'boolean',
|
||||||
'has_pst' => 'boolean',
|
'has_pst' => 'boolean',
|
||||||
|
'has_hst' => 'boolean',
|
||||||
'date' => 'datetime',
|
'date' => 'datetime',
|
||||||
'status' => InvoiceStatus::class,
|
'status' => InvoiceStatus::class,
|
||||||
'subtotal' => 'float',
|
'subtotal' => 'float',
|
||||||
'pst_amount' => 'float',
|
'pst_amount' => 'float',
|
||||||
'gst_amount' => 'float',
|
'gst_amount' => 'float',
|
||||||
|
'hst_amount' => 'float',
|
||||||
'total' => 'float',
|
'total' => 'float',
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -60,23 +64,26 @@ public function calculateTotals(): void
|
|||||||
$this->subtotal = 0;
|
$this->subtotal = 0;
|
||||||
$this->gst_amount = 0;
|
$this->gst_amount = 0;
|
||||||
$this->pst_amount = 0;
|
$this->pst_amount = 0;
|
||||||
|
$this->hst_amount = 0;
|
||||||
$this->total = 0;
|
$this->total = 0;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$subtotal = $this->orders->sum(fn (Order $order) => $order->total_service_price);
|
$subtotal = $this->orders->sum(fn (Order $order) => $order->total_service_price);
|
||||||
Log::debug('subtotal: '.$subtotal);
|
|
||||||
|
|
||||||
$this->subtotal = $subtotal;
|
$this->subtotal = $subtotal;
|
||||||
$this->saveQuietly();
|
$this->saveQuietly();
|
||||||
|
|
||||||
$gstAmount = $this->calculateTaxAmount($subtotal, $this->gst_rate, $this->has_gst);
|
$gstAmount = $this->calculateTaxAmount($subtotal, $this->gst_rate, $this->has_gst);
|
||||||
$pstAmount = $this->calculateTaxAmount($subtotal, $this->pst_rate, $this->has_pst);
|
$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->gst_amount = $gstAmount;
|
||||||
$this->pst_amount = $pstAmount;
|
$this->pst_amount = $pstAmount;
|
||||||
$this->total = $subtotal + $gstAmount + $pstAmount;
|
$this->hst_amount = $hstAmount;
|
||||||
|
|
||||||
|
$this->total = $subtotal + $gstAmount + $pstAmount + $hstAmount;
|
||||||
|
|
||||||
$this->saveQuietly();
|
$this->saveQuietly();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
use Database\Factories\UserFactory;
|
use Database\Factories\UserFactory;
|
||||||
use Filament\Models\Contracts\HasName;
|
use Filament\Models\Contracts\HasName;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ class User extends Authenticatable implements HasName
|
|||||||
'username',
|
'username',
|
||||||
'is_admin',
|
'is_admin',
|
||||||
'password',
|
'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
|
public function getFilamentName(): string
|
||||||
{
|
{
|
||||||
return $this->username;
|
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->pst_rate = TaxRate::where('name', 'PST')->value('value') ?? 0;
|
||||||
$invoice->gst_rate = TaxRate::where('name', 'GST')->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;
|
namespace App\Providers\Filament;
|
||||||
|
|
||||||
|
use App\Filament\Customer\Pages\CustomerLogin;
|
||||||
use Filament\Http\Middleware\Authenticate;
|
use Filament\Http\Middleware\Authenticate;
|
||||||
use Filament\Http\Middleware\DisableBladeIconComponents;
|
use Filament\Http\Middleware\DisableBladeIconComponents;
|
||||||
use Filament\Http\Middleware\DispatchServingFilamentEvent;
|
use Filament\Http\Middleware\DispatchServingFilamentEvent;
|
||||||
@ -9,7 +10,6 @@
|
|||||||
use Filament\Panel;
|
use Filament\Panel;
|
||||||
use Filament\PanelProvider;
|
use Filament\PanelProvider;
|
||||||
use Filament\Support\Colors\Color;
|
use Filament\Support\Colors\Color;
|
||||||
use Filament\Widgets;
|
|
||||||
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
||||||
use Illuminate\Cookie\Middleware\EncryptCookies;
|
use Illuminate\Cookie\Middleware\EncryptCookies;
|
||||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
|
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
|
||||||
@ -35,11 +35,9 @@ public function panel(Panel $panel): Panel
|
|||||||
// ->pages([
|
// ->pages([
|
||||||
// Pages\Dashboard::class,
|
// Pages\Dashboard::class,
|
||||||
// ])
|
// ])
|
||||||
|
->login(CustomerLogin::class)
|
||||||
->discoverWidgets(in: app_path('Filament/Customer/Widgets'), for: 'App\\Filament\\Customer\\Widgets')
|
->discoverWidgets(in: app_path('Filament/Customer/Widgets'), for: 'App\\Filament\\Customer\\Widgets')
|
||||||
->widgets([
|
->widgets([])
|
||||||
Widgets\AccountWidget::class,
|
|
||||||
Widgets\FilamentInfoWidget::class,
|
|
||||||
])
|
|
||||||
->middleware([
|
->middleware([
|
||||||
EncryptCookies::class,
|
EncryptCookies::class,
|
||||||
AddQueuedCookiesToResponse::class,
|
AddQueuedCookiesToResponse::class,
|
||||||
|
@ -19,10 +19,12 @@ public function definition(): array
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'created_at' => Carbon::now()->subDays(rand(1, 30)),
|
'created_at' => Carbon::now()->subDays(rand(1, 30)),
|
||||||
'pst_rate' => TaxRate::where('name', 'PST')->value('value'),
|
'pst_rate' => TaxRate::where('name', 'PST')->value('value') ?? 0,
|
||||||
'gst_rate' => TaxRate::where('name', 'GST')->value('value'),
|
'gst_rate' => TaxRate::where('name', 'GST')->value('value') ?? 0,
|
||||||
|
'hst_rate' => TaxRate::where('name', 'HST')->value('value') ?? 0,
|
||||||
'has_gst' => true,
|
'has_gst' => true,
|
||||||
'has_pst' => $this->faker->boolean(40),
|
'has_pst' => $this->faker->boolean(40),
|
||||||
|
'has_hst' => false,
|
||||||
'date' => Carbon::now()->subDays(rand(1, 60)),
|
'date' => Carbon::now()->subDays(rand(1, 60)),
|
||||||
'status' => $this->faker->randomElement(InvoiceStatus::cases())->value,
|
'status' => $this->faker->randomElement(InvoiceStatus::cases())->value,
|
||||||
'customer_id' => $customer->id,
|
'customer_id' => $customer->id,
|
||||||
|
@ -13,6 +13,7 @@ public function up(): void
|
|||||||
{
|
{
|
||||||
Schema::create('users', function (Blueprint $table) {
|
Schema::create('users', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
|
$table->foreignId('customer_id')->nullable()->constrained();
|
||||||
$table->string('username')->unique();
|
$table->string('username')->unique();
|
||||||
$table->string('password');
|
$table->string('password');
|
||||||
$table->boolean('is_admin')->default(0);
|
$table->boolean('is_admin')->default(0);
|
@ -21,12 +21,15 @@ public function up(): void
|
|||||||
|
|
||||||
$table->decimal('pst_rate', 8, 2);
|
$table->decimal('pst_rate', 8, 2);
|
||||||
$table->decimal('gst_rate', 8, 2);
|
$table->decimal('gst_rate', 8, 2);
|
||||||
|
$table->decimal('hst_rate', 8, 2);
|
||||||
|
|
||||||
$table->decimal('pst_amount', 8, 2)->nullable();
|
$table->decimal('pst_amount', 8, 2)->nullable();
|
||||||
$table->decimal('gst_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_pst')->default(false);
|
||||||
$table->boolean('has_gst')->default(true);
|
$table->boolean('has_gst')->default(true);
|
||||||
|
$table->boolean('has_hst')->default(false);
|
||||||
|
|
||||||
$table->date('date')->default(today());
|
$table->date('date')->default(today());
|
||||||
$table->date('due_date')->nullable();
|
$table->date('due_date')->nullable();
|
||||||
|
@ -17,6 +17,7 @@ public function run(): void
|
|||||||
$this->call([
|
$this->call([
|
||||||
TaxRateSeeder::class,
|
TaxRateSeeder::class,
|
||||||
CustomerSeeder::class,
|
CustomerSeeder::class,
|
||||||
|
UserSeeder::class,
|
||||||
ContactSeeder::class,
|
ContactSeeder::class,
|
||||||
ShippingEntrySeeder::class,
|
ShippingEntrySeeder::class,
|
||||||
OrderSeeder::class,
|
OrderSeeder::class,
|
||||||
|
@ -14,5 +14,6 @@ public function run(): void
|
|||||||
{
|
{
|
||||||
TaxRate::create(['name' => 'GST', 'value' => 5.00]);
|
TaxRate::create(['name' => 'GST', 'value' => 5.00]);
|
||||||
TaxRate::create(['name' => 'PST', 'value' => 7.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
|
$attributes
|
||||||
->merge($getExtraAttributes(), escape: false)
|
->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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if($isAddable)
|
|
||||||
<div class="relative flex justify-center py-2">
|
|
||||||
{{ $addAction }}
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@if($isAddable)
|
||||||
|
<div class="relative flex justify-center py-2">
|
||||||
|
{{ $addAction }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
</x-dynamic-component>
|
</x-dynamic-component>
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
$customer = Customer::factory()->create(); // Generates a customer
|
$customer = Customer::factory()->create(); // Generates a customer
|
||||||
$pst_rate = TaxRate::where('name', 'PST')->value('value') ?? 0;
|
$pst_rate = TaxRate::where('name', 'PST')->value('value') ?? 0;
|
||||||
$gst_rate = TaxRate::where('name', 'GST')->value('value') ?? 0;
|
$gst_rate = TaxRate::where('name', 'GST')->value('value') ?? 0;
|
||||||
|
$hst_rate = TaxRate::where('name', 'HST')->value('value') ?? 0;
|
||||||
|
|
||||||
$formData = [
|
$formData = [
|
||||||
'customer_id' => $customer->id,
|
'customer_id' => $customer->id,
|
||||||
@ -27,6 +28,7 @@
|
|||||||
'status' => InvoiceStatus::UNPAID->value,
|
'status' => InvoiceStatus::UNPAID->value,
|
||||||
'has_gst' => true,
|
'has_gst' => true,
|
||||||
'has_pst' => true,
|
'has_pst' => true,
|
||||||
|
'has_hst' => false,
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->livewire(CreateInvoice::class)
|
$this->livewire(CreateInvoice::class)
|
||||||
@ -40,8 +42,10 @@
|
|||||||
'status' => $formData['status'],
|
'status' => $formData['status'],
|
||||||
'has_gst' => $formData['has_gst'],
|
'has_gst' => $formData['has_gst'],
|
||||||
'has_pst' => $formData['has_pst'],
|
'has_pst' => $formData['has_pst'],
|
||||||
|
'has_hst' => $formData['has_hst'],
|
||||||
'gst_rate' => $gst_rate,
|
'gst_rate' => $gst_rate,
|
||||||
'pst_rate' => $pst_rate,
|
'pst_rate' => $pst_rate,
|
||||||
|
'hst_rate' => $hst_rate,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$invoice = Invoice::where('internal_id', 'INV400001')->firstOrFail();
|
$invoice = Invoice::where('internal_id', 'INV400001')->firstOrFail();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user