diff --git a/app/Filament/Resources/InvoiceReportResource.php b/app/Filament/Resources/InvoiceReportResource.php index e53aa51..fcadbe8 100644 --- a/app/Filament/Resources/InvoiceReportResource.php +++ b/app/Filament/Resources/InvoiceReportResource.php @@ -11,6 +11,7 @@ use Filament\Forms\Form; use Filament\Resources\Resource; use Filament\Support\Enums\FontFamily; +use Filament\Support\Enums\FontWeight; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; @@ -72,6 +73,7 @@ public static function table(Table $table): Table ->label('End Date') ->date('Y-m-d'), TextColumn::make('total') + ->weight(FontWeight::Bold) ->money(), ]) ->defaultSort('created_at', 'desc') @@ -103,7 +105,7 @@ public static function getPages(): array { return [ 'index' => Pages\ListInvoiceReports::route('/'), - 'edit' => Pages\EditInvoiceReport::route('/{record}/edit'), + 'view' => Pages\ViewInvoiceReport::route('/{record}'), 'create' => Pages\CreateInvoiceReport::route('/create'), ]; } diff --git a/app/Filament/Resources/InvoiceReportResource/Pages/ViewInvoiceReport.php b/app/Filament/Resources/InvoiceReportResource/Pages/ViewInvoiceReport.php index 7a28647..7d621bc 100644 --- a/app/Filament/Resources/InvoiceReportResource/Pages/ViewInvoiceReport.php +++ b/app/Filament/Resources/InvoiceReportResource/Pages/ViewInvoiceReport.php @@ -3,6 +3,8 @@ namespace App\Filament\Resources\InvoiceReportResource\Pages; use App\Filament\Resources\InvoiceReportResource; +use App\Models\InvoiceReport; +use Filament\Actions\Action; use Filament\Resources\Pages\ViewRecord; class ViewInvoiceReport extends ViewRecord @@ -14,6 +16,10 @@ class ViewInvoiceReport extends ViewRecord protected function getHeaderActions(): array { return [ + Action::make('print') + ->icon('lucide-printer') + ->url(fn (InvoiceReport $record) => route('pdf.invoice-report', $record)) + ->openUrlInNewTab(), ]; } } diff --git a/app/Filament/Resources/InvoiceReportResource/RelationManagers/InvoicesRelationManager.php b/app/Filament/Resources/InvoiceReportResource/RelationManagers/InvoicesRelationManager.php index 993f67a..4e6c170 100644 --- a/app/Filament/Resources/InvoiceReportResource/RelationManagers/InvoicesRelationManager.php +++ b/app/Filament/Resources/InvoiceReportResource/RelationManagers/InvoicesRelationManager.php @@ -2,10 +2,12 @@ namespace App\Filament\Resources\InvoiceReportResource\RelationManagers; +use App\Filament\Resources\InvoiceResource; use Filament\Forms; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Tables; +use Filament\Support\Enums\FontWeight; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; class InvoicesRelationManager extends RelationManager @@ -26,25 +28,40 @@ public function table(Table $table): Table { return $table ->recordTitleAttribute('internal_id') + ->recordUrl(fn ($record) => InvoiceResource::getUrl('edit', ['record' => $record->id])) ->columns([ - Tables\Columns\TextColumn::make('internal_id'), + TextColumn::make('internal_id') + ->label('ID') + ->extraHeaderAttributes(['class' => 'w-full']) + ->color('primary'), + TextColumn::make('date') + ->label('Created') + ->date(), + TextColumn::make('subtotal') + ->alignRight() + ->money(), + TextColumn::make('gst_amount') + ->alignRight() + ->money(), + TextColumn::make('pst_amount') + ->alignRight() + ->formatStateUsing(function ($state) { + return $state == 0.00 ? '-' : '$'.$state; + }), + TextColumn::make('total') + ->alignRight() + ->money() + ->weight(FontWeight::Bold), + TextColumn::make('status'), ]) ->filters([ // ]) ->headerActions([ - // Tables\Actions\CreateAction::make(), - Tables\Actions\AssociateAction::make(), ]) ->actions([ - Tables\Actions\DissociateAction::make(), - // Tables\Actions\EditAction::make(), - // Tables\Actions\DeleteAction::make(), ]) ->bulkActions([ - // Tables\Actions\BulkActionGroup::make([ - // Tables\Actions\DeleteBulkAction::make(), - // ]), ]); } } diff --git a/app/Filament/Resources/OrderResource.php b/app/Filament/Resources/OrderResource.php index 4d6192c..dd9327e 100644 --- a/app/Filament/Resources/OrderResource.php +++ b/app/Filament/Resources/OrderResource.php @@ -151,10 +151,22 @@ public static function form(Form $form): Form Grid::make(19) ->schema([ Select::make('serviceType') - ->options(ServiceType::all()->pluck('name', 'id')) - ->columnSpan(2) + ->options(ServiceType::all()->pluck('value', 'id')) + ->columnSpan(4) ->placeholder('Select...') - ->searchable(), + ->searchable() + ->createOptionForm([ + TextInput::make('name') + ->label('Code') + ->placeholder('Abbreviation here (example: \'Emb\'') + ->required(), + TextInput::make('value') + ->placeholder('Full name here (example: \'Embroidery\'') + ->required(), + ]) + ->createOptionUsing(function (array $data): int { + return ServiceType::create($data)->getKey(); + }), TextInput::make('placement') ->columnSpan(3), TextInput::make('serviceFileName') @@ -176,31 +188,32 @@ public static function form(Form $form): Form TextInput::make('amount') ->label('Quantity') ->live() - ->reactive() - ->afterStateUpdated(function ($state, Get $get, Set $set) { - $set('total_price', ($get('amount_price') * $state ?? 0)); - }) - ->afterStateHydrated(function ($state, Get $get, Set $set) { - $set('total_price', ($get('amount_price') * $state ?? 0)); - }) +// ->reactive() +// ->afterStateUpdated(function ($state, Get $get, Set $set) { +// $set('total_price', ($get('amount_price') * $state ?? 0)); +// }) +// ->afterStateHydrated(function ($state, Get $get, Set $set) { +// $set('total_price', ($get('amount_price') * $state ?? 0)); +// }) ->prefix('#') ->columnSpan(2), TextInput::make('amount_price') + ->label('Amount') ->prefix('$') - ->reactive() - ->afterStateUpdated(function ($state, Get $get, Set $set) { - $set('total_price', ($get('amount') * $state ?? 0)); - }) - ->afterStateHydrated(function ($state, Get $get, Set $set) { - $set('total_price', ($get('amount') * $state ?? 0)); - }) +// ->reactive() +// ->afterStateUpdated(function ($state, Get $get, Set $set) { +// $set('total_price', ($get('amount') * $state ?? 0)); +// }) +// ->afterStateHydrated(function ($state, Get $get, Set $set) { +// $set('total_price', ($get('amount') * $state ?? 0)); +// }) ->columnSpan(2), - TextInput::make('total_price') - ->prefix('$') - ->readOnly() - ->columnSpan(2), + // TextInput::make('total_price') + // ->prefix('$') + // ->readOnly() + // ->columnSpan(2), ]), Grid::make(9) diff --git a/app/Filament/Resources/OrderResource/Pages/ListOrders.php b/app/Filament/Resources/OrderResource/Pages/ListOrders.php index a22cb38..4ad5e60 100644 --- a/app/Filament/Resources/OrderResource/Pages/ListOrders.php +++ b/app/Filament/Resources/OrderResource/Pages/ListOrders.php @@ -36,6 +36,19 @@ public function getTabs(): array ->whereNot('status', OrderStatus::INVOICED) ->count(); }), + + 'unprinted' => Tab::make() + ->query(function ($query) { + return $query->where('printed', false); + }) + ->icon('lucide-printer') + ->badge(function () { + $count = Order::where('printed', false)->count(); + + return $count > 0 ? $count : null; + }) + ->badgeColor('success'), + 'overdue' => Tab::make() ->query(function ($query) { return $query->whereDate('due_date', '<=', today()) diff --git a/app/Filament/Resources/PackingSlipResource.php b/app/Filament/Resources/PackingSlipResource.php index e93148b..ecd9267 100644 --- a/app/Filament/Resources/PackingSlipResource.php +++ b/app/Filament/Resources/PackingSlipResource.php @@ -31,7 +31,8 @@ public static function form(Form $form): Form return $form ->schema([ DatePicker::make('date_received'), - TextInput::make('amount'), + TextInput::make('amount') + ->label('Quantity'), Select::make('customer_id') ->options(Customer::all()->pluck('company_name', 'id')) ->reactive() @@ -59,7 +60,8 @@ public static function table(Table $table): Table ->sortable() ->searchable(), TextColumn::make('contents'), - TextColumn::make('amount'), + TextColumn::make('amount') + ->label('Quantity'), TextColumn::make('order.customer.company_name') ->sortable() ->searchable(), diff --git a/app/Http/Controllers/PdfController.php b/app/Http/Controllers/PdfController.php new file mode 100644 index 0000000..af9ec13 --- /dev/null +++ b/app/Http/Controllers/PdfController.php @@ -0,0 +1,26 @@ +internal_id.'.pdf'); + + Pdf::view('pdf.invoice-report', ['invoiceReport' => $invoiceReport]) + ->withBrowsershot(function (Browsershot $browsershot) { + $browsershot->noSandbox(); + }) + ->margins(8, 8, 15, 8) + ->footerView('pdf.invoice-report-footer', ['invoiceReport' => $invoiceReport]) + ->save($url); + + return redirect($url); + } +} diff --git a/app/Models/InvoiceReport.php b/app/Models/InvoiceReport.php index 7e20a28..c9fd575 100644 --- a/app/Models/InvoiceReport.php +++ b/app/Models/InvoiceReport.php @@ -6,7 +6,6 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; -use Illuminate\Database\Eloquent\Relations\HasManyThrough; class InvoiceReport extends Model { @@ -28,8 +27,19 @@ public static function boot(): void { parent::boot(); - static::created(function ($model) { + static::created(function (InvoiceReport $model) { + + // Set ID after creation $model->attributes['internal_id'] = 'TN-INR-'.$model->id; + + // Associate all relevant invoices + $invoices = Invoice::whereBetween('date', [$model->date_start, $model->date_end]) + ->where('customer_id', $model->customer_id); + $model->invoices()->sync($invoices->pluck('id')->toArray()); + + $model->total = $model->invoices()->sum('total'); + + // Finally, save $model->save(); }); } @@ -44,8 +54,8 @@ public function invoices(): BelongsToMany return $this->BelongsToMany(Invoice::class); } - public function orders(): HasManyThrough + public function orders() { - return $this->hasManyThrough(Order::class, Invoice::class); + return $this->invoices()->with('orders')->get()->pluck('orders')->flatten()->unique('id'); } } diff --git a/public/invoice-tn-in-24-0017.pdf b/public/invoice-tn-in-24-0017.pdf new file mode 100644 index 0000000..2cc3ed0 Binary files /dev/null and b/public/invoice-tn-in-24-0017.pdf differ diff --git a/public/invoicereport-tn-inr-1.pdf b/public/invoicereport-tn-inr-1.pdf new file mode 100644 index 0000000..b6aa767 Binary files /dev/null and b/public/invoicereport-tn-inr-1.pdf differ diff --git a/public/invoicereport-tn-inr-3.pdf b/public/invoicereport-tn-inr-3.pdf new file mode 100644 index 0000000..aee4746 Binary files /dev/null and b/public/invoicereport-tn-inr-3.pdf differ diff --git a/public/order-tn24-0029.pdf b/public/order-tn24-0029.pdf new file mode 100644 index 0000000..ed1907a Binary files /dev/null and b/public/order-tn24-0029.pdf differ diff --git a/resources/views/pdf/invoice-report-footer.blade.php b/resources/views/pdf/invoice-report-footer.blade.php new file mode 100644 index 0000000..7e7c2e0 --- /dev/null +++ b/resources/views/pdf/invoice-report-footer.blade.php @@ -0,0 +1,10 @@ + + +' \ No newline at end of file diff --git a/resources/views/pdf/invoice-report.blade.php b/resources/views/pdf/invoice-report.blade.php new file mode 100644 index 0000000..f0cafa9 --- /dev/null +++ b/resources/views/pdf/invoice-report.blade.php @@ -0,0 +1,90 @@ +@extends('layouts.pdf') + + + +
Date | +Invoice | +Subtotal | +PST | +GST | +Total | +
---|---|---|---|---|---|
{{Date::make($invoice->created_at)->format('Y-m-d')}} | +{{$invoice->internal_id}} | +${{$invoice->subtotal}} | +{{!$invoice->pst_amount ? '-' : '$'.number_format($invoice->pst_amount, 2)}} | +${{number_format($invoice->gst_amount, 2)}} | +${{$invoice->total}} | +