Work on invoice PDF

to do
- split address lines in two
- look into footer
orders
Nisse Lommerde 2 weeks ago
parent 1b891f8350
commit 2de11bcaba

@ -17,6 +17,8 @@ use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
class InvoiceResource extends Resource
{
@ -71,6 +73,10 @@ class InvoiceResource extends Resource
'true' => 'info',
'false' => 'info',
]),
ToggleButtons::make('paid')
->boolean()
->default(false)
->inline(),
])->columnSpan(1),
])
->columns(3)
@ -84,10 +90,16 @@ class InvoiceResource extends Resource
->columns([
Tables\Columns\TextColumn::make('internal_id')
->label('ID')
->color('primary'),
Tables\Columns\TextColumn::make('customer.company_name'),
->fontFamily('mono')
->color('primary')
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('customer.company_name')
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('created_at')
->date(),
->date()
->sortable(),
Tables\Columns\TextColumn::make('gst_amount')
->label('GST')
->prefix('$'),
@ -97,20 +109,55 @@ class InvoiceResource extends Resource
Tables\Columns\TextColumn::make('subtotal')
->prefix('$'),
Tables\Columns\TextColumn::make('total')
->prefix('$'),
->prefix('$')
->weight('bold'),
Tables\Columns\IconColumn::make('paid')
->boolean()
->sortable(),
])
->filters([
//
])
Tables\Filters\Filter::make('created_at')
->form([
Split::make([
DatePicker::make('created_from')
->label('From date'),
DatePicker::make('created_until')
->label('Until date'),
]),
])
->query(function (Builder $query, array $data): Builder {
return $query
->when(
$data['created_from'],
fn (Builder $query, $date): Builder => $query->whereDate('date', '>=', $date),
)
->when(
$data['created_until'],
fn (Builder $query, $date): Builder => $query->whereDate('date', '<=', $date),
);
}),
Tables\Filters\Filter::make('paid'),
], layout: Tables\Enums\FiltersLayout::AboveContentCollapsible)
->filtersFormColumns(3)
->defaultSort('created_at', 'desc')
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkAction::make('Mark as paid')
->action(fn (Collection $records) => $records->each->setPaid(true))
->icon('lucide-circle-check')
->deselectRecordsAfterCompletion(),
Tables\Actions\BulkActionGroup::make([
Tables\Actions\BulkAction::make('Mark as unpaid')
->action(fn (Collection $records) => $records->each->setPaid(false))
->icon('lucide-circle-x')
->deselectRecordsAfterCompletion(),
Tables\Actions\DeleteBulkAction::make(),
]),
]);
])
->label('Other actions'),
])
->selectCurrentPageOnly();
}
public static function getRelations(): array

@ -27,6 +27,7 @@ use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Guava\FilamentClusters\Forms\Cluster;
use Icetalker\FilamentTableRepeater\Forms\Components\TableRepeater;
use Illuminate\Database\Eloquent\Builder;
class OrderResource extends Resource
{
@ -255,22 +256,25 @@ class OrderResource extends Resource
->searchable()
->sortable(),
])
->recordClasses(function (Order $order) {
if ($order->rush) {
return 'bg-green-100';
}
return '';
})
->defaultSort('order_date', 'desc')
->groups([
'status',
])
->filters([
Tables\Filters\SelectFilter::make('status')
->multiple()
->options(OrderStatus::class),
])
Tables\Filters\Filter::make('order_date')
->form([
DatePicker::make('created_from'),
DatePicker::make('created_until'),
])
->query(function (Builder $query, array $data): Builder {
return $query
->when(
$data['created_from'],
fn (Builder $query, $date): Builder => $query->whereDate('order_date', '>=', $date),
)
->when(
$data['created_until'],
fn (Builder $query, $date): Builder => $query->whereDate('order_date', '<=', $date),
);
}),
], layout: Tables\Enums\FiltersLayout::AboveContentCollapsible)
->actions([
Tables\Actions\EditAction::make(),
])
@ -292,8 +296,7 @@ class OrderResource extends Resource
return [
'index' => Pages\ListOrders::route('/'),
'create' => Pages\CreateOrder::route('/create'),
// 'view' => Pages\ViewOrder::route('/{record}'),
'edit' => Pages\EditOrder::route('/{record}/edit'),
'edit' => Pages\EditOrder::route('/{record}/edit'),
];
}
}

@ -14,6 +14,7 @@ class Invoice extends Model
protected $fillable = [
'customer_id',
'internal_id',
'subtotal',
'total',
'gst',
@ -23,7 +24,6 @@ class Invoice extends Model
];
protected $appends = [
'internal_id',
'gst_amount',
'pst_amount',
];
@ -33,9 +33,27 @@ class Invoice extends Model
'subtotal' => 'decimal:2',
];
public function getInternalIdAttribute(): string
public static function boot(): void
{
parent::boot();
static::created(function ($model) {
$model->attributes['internal_id'] = $model->generateInternalId($model->id);
$model->save();
});
}
public function setPaid(bool $value): void
{
if ($this->paid != $value) {
$this->paid = $value;
$this->save();
}
}
public function generateInternalId(int $id): string
{
$po = str_pad(strval($this->id), 4, '0', STR_PAD_LEFT);
$po = str_pad(strval($id), 4, '0', STR_PAD_LEFT);
$year = date('y');
return 'TN-IN-'.$year.'-'.$po;

@ -38,7 +38,7 @@ class ProductService extends Model
{
$file = $this->serviceFile;
return $file->name.' '.$this->placement.' '.$file->width.' W '.$file->height.' H';
return $file->name.', '.$this->placement.', '.$file->width.' W, '.$file->height.' H';
}
/**

@ -16,7 +16,7 @@ class InvoiceFactory extends Factory
$customer = Customer::all()->shuffle()->first();
return [
'created_at' => Carbon::now(),
'created_at' => Carbon::now()->subDays(rand(1, 30)),
'gst' => true,
'pst' => $this->faker->boolean(25),
'paid' => $this->faker->boolean(),

@ -10,8 +10,9 @@ return new class extends Migration
{
Schema::create('invoices', function (Blueprint $table) {
$table->id();
$table->string('internal_id')->nullable();
$table->foreignId('customer_id')->constrained()->nullable();
$table->foreignId('customer_id')->nullable()->constrained();
$table->float('subtotal', 2)->default(0.00);
$table->float('total', 2)->default(0.00);

@ -24,7 +24,7 @@ class DatabaseSeeder extends Seeder
ProductServiceSeeder::class,
ServiceFileSeeder::class,
QuoteSeeder::class,
// InvoiceSeeder::class,
InvoiceSeeder::class,
]);
User::factory()->create([

201
package-lock.json generated

@ -6,7 +6,7 @@
"": {
"dependencies": {
"bootstrap-icons": "^1.11.3",
"puppeteer": "^23.6.0"
"puppeteer": "^23.7.1"
},
"devDependencies": {
"@popperjs/core": "^2.11.6",
@ -34,12 +34,13 @@
}
},
"node_modules/@babel/code-frame": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.9.tgz",
"integrity": "sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ==",
"version": "7.26.2",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
"integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
"license": "MIT",
"dependencies": {
"@babel/highlight": "^7.25.9",
"@babel/helper-validator-identifier": "^7.25.9",
"js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
},
"engines": {
@ -55,21 +56,6 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/highlight": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz",
"integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==",
"license": "MIT",
"dependencies": {
"@babel/helper-validator-identifier": "^7.25.9",
"chalk": "^2.4.2",
"js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
@ -678,12 +664,12 @@
}
},
"node_modules/@puppeteer/browsers": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.4.0.tgz",
"integrity": "sha512-x8J1csfIygOwf6D6qUAZ0ASk3z63zPb7wkNeHRerCMh82qWKUrOgkuP005AJC8lDL6/evtXETGEJVcwykKT4/g==",
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.4.1.tgz",
"integrity": "sha512-0kdAbmic3J09I6dT8e9vE2JOCSt13wHCW5x/ly8TSt2bDtuIWe2TgLZZDHdcziw9AVCzflMAXCrVyRIhIs44Ng==",
"license": "Apache-2.0",
"dependencies": {
"debug": "^4.3.6",
"debug": "^4.3.7",
"extract-zip": "^2.0.1",
"progress": "^2.0.3",
"proxy-agent": "^6.4.0",
@ -978,15 +964,18 @@
}
},
"node_modules/ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"license": "MIT",
"dependencies": {
"color-convert": "^1.9.0"
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=4"
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/any-promise": {
@ -1358,20 +1347,6 @@
],
"license": "CC-BY-4.0"
},
"node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@ -1426,18 +1401,21 @@
}
},
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"license": "MIT",
"dependencies": {
"color-name": "1.1.3"
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"license": "MIT"
},
"node_modules/combined-stream": {
@ -1682,15 +1660,6 @@
"node": ">=6"
}
},
"node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"license": "MIT",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/escodegen": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
@ -2003,15 +1972,6 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC"
},
"node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
@ -2848,17 +2808,17 @@
}
},
"node_modules/puppeteer": {
"version": "23.6.0",
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.6.0.tgz",
"integrity": "sha512-l+Fgo8SVFSd51STtq2crz8t1Y3VXowsuR4zfR64qDOn6oggz7YIZauWiNR4IJjczQ6nvFs3S4cgng55/nesxTQ==",
"version": "23.7.1",
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.7.1.tgz",
"integrity": "sha512-jS6XehagMvxQ12etwY/4EOYZ0Sm8GAsrtGhdQn4AqpJAyHc3RYl7tGd4QYh/MmShDw8sF9FWYQqGidhoXaqokQ==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@puppeteer/browsers": "2.4.0",
"@puppeteer/browsers": "2.4.1",
"chromium-bidi": "0.8.0",
"cosmiconfig": "^9.0.0",
"devtools-protocol": "0.0.1354347",
"puppeteer-core": "23.6.0",
"puppeteer-core": "23.7.1",
"typed-query-selector": "^2.12.0"
},
"bin": {
@ -2869,12 +2829,12 @@
}
},
"node_modules/puppeteer-core": {
"version": "23.6.0",
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.6.0.tgz",
"integrity": "sha512-se1bhgUpR9C529SgHGr/eyT92mYyQPAhA2S9pGtGrVG2xob9qE6Pbp7TlqiSPlnnY1lINqhn6/67EwkdzOmKqQ==",
"version": "23.7.1",
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.7.1.tgz",
"integrity": "sha512-Om/qCZhd+HLoAr7GltrRAZpS3uOXwHu7tXAoDbNcJADHjG2zeAlDArgyIPXYGG4QB/EQUHk13Q6RklNxGM73Pg==",
"license": "Apache-2.0",
"dependencies": {
"@puppeteer/browsers": "2.4.0",
"@puppeteer/browsers": "2.4.1",
"chromium-bidi": "0.8.0",
"debug": "^4.3.7",
"devtools-protocol": "0.0.1354347",
@ -3265,18 +3225,6 @@
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"license": "MIT",
"dependencies": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
@ -3422,9 +3370,9 @@
"license": "Apache-2.0"
},
"node_modules/tslib": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
"integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==",
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
"node_modules/typed-query-selector": {
@ -3626,75 +3574,6 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/wrap-ansi-cjs/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"license": "MIT"
},
"node_modules/wrap-ansi/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrap-ansi/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/wrap-ansi/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"license": "MIT"
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",

@ -18,6 +18,6 @@
},
"dependencies": {
"bootstrap-icons": "^1.11.3",
"puppeteer": "^23.6.0"
"puppeteer": "^23.7.1"
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -1,6 +1,6 @@
@extends('layouts.pdf')
<div class="container-fluid ">
<div class="container-fluid pt-4 font-serif" style="font-size: 0.9rem">
<div class="fw-bold">
TOP NOTCH EMBROIDERY & DIGITIZING LTD
</div>
@ -11,45 +11,50 @@
info@sewtopnotch.com <br>
GST# 846025062RT0001 <br>
</div>
<div class="fs-3">
<div class="fs-3 fw-bold text-primary mt-2">
INVOICE
</div>
<div class="fw-bold">
BILL TO
</div>
<div>
{{$invoice->customer->company_name}} <br>
{{$invoice->customer->billing_address}} <br>
</div>
{{-- split right--}}
<div>
<span class="fw-bold">
INVOICE#
</span>
{{$invoice->internal_id}}
</div>
<div>
<span class="fw-bold">
DATE
</span>
{{$invoice->date}}
</div>
<div>
<span class="fw-bold">
DUE DATE
</span>
{{$invoice->due_date}}
</div>
<div>
<span class="fw-bold">
TERMS
</span>
<div class="d-flex flex-row">
<div class="me-auto">
<div class="fw-bold">
BILL TO
</div>
<div>
{{$invoice->customer->company_name}} <br>
{{$invoice->customer->billing_address}} <br>
</div>
</div>
<div class="text-end pe-2">
<div class="fw-bold">
INVOICE#
</div>
<div class="fw-bold">
DATE
</div>
<div class="fw-bold">
DUE DATE
</div>
</div>
<div>
<div>
{{$invoice->internal_id}}
</div>
<div>
{{$invoice->date}}
</div>
<div>
{{$invoice->due_date}}
</div>
</div>
</div>
<hr>
<table>
<table class="table table-sm table-striped">
<tr>
<th>WO#</th>
<th>PO#</th>
@ -61,28 +66,52 @@
@foreach($invoice->productServices as $service)
<tr>
<td>
<span style="font-size: 0.9rem">
{{$service->order->internal_po}}
</span>
</td>
<td>
{{$service->order->customer_po}}
</td>
<td>
<span class="fw-bold">
{{$service->order->order_type->name}} <br>
</span>
{{$service->service_details}}
</td>
<td>
<td class="text-end">
{{$service->amount}}
</td>
<td>
{{$service->amount_price}}
<td class="text-end">
{{number_format($service->amount_price, 2)}}
</td>
<td>
${{$service->price}}
<td class="text-end">
${{number_Format($service->price, 2)}}
</td>
</tr>
@endforeach
</table>
<div class="d-flex flex-row-reverse">
<div class="text-end ps-5">
<div>${{number_format($invoice->subtotal, 2)}}</div>
<div>${{number_format($invoice->gst_amount, 2)}}</div>
<div>${{number_format($invoice->pst_amount, 2)}}</div>
<div>${{number_format($invoice->total, 2)}}</div>
<br>
<div class="fw-bold">${{number_format($invoice->total, 2)}}</div>
</div>
<div class="fw-bold text-end">
<div>Subtotal</div>
<div>GST @ 5%</div>
<div>PST (BC) @ 7%</div>
<div>TOTAL</div>
<br>
<div>BALANCE DUE</div>
</div>
</div>
</div>

Loading…
Cancel
Save