More work on shippingEntries
Table groupified + search working despite lack of column; create/edit form
This commit is contained in:
parent
487ea48c14
commit
548e56335f
@ -2,9 +2,28 @@
|
|||||||
|
|
||||||
namespace App\Enums;
|
namespace App\Enums;
|
||||||
|
|
||||||
enum ShippingType: string
|
use Filament\Support\Contracts\HasIcon;
|
||||||
|
use Filament\Support\Contracts\HasLabel;
|
||||||
|
|
||||||
|
enum ShippingType: string implements HasIcon, HasLabel
|
||||||
{
|
{
|
||||||
case THEY_SHIP = 'They ship';
|
case THEY_SHIP = 'They ship';
|
||||||
case WE_SHIP = 'We ship';
|
case WE_SHIP = 'We ship';
|
||||||
case PICKUP = 'Pickup';
|
case PICKUP = 'Pickup';
|
||||||
|
case OTHER = 'Other';
|
||||||
|
|
||||||
|
public function getLabel(): ?string
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIcon(): ?string
|
||||||
|
{
|
||||||
|
return match ($this) {
|
||||||
|
self::THEY_SHIP => 'lucide-truck',
|
||||||
|
self::WE_SHIP => 'lucide-house',
|
||||||
|
self::PICKUP => 'lucide-handshake',
|
||||||
|
self::OTHER => 'lucide-ellipsis'
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,24 @@
|
|||||||
|
|
||||||
namespace App\Filament\Resources;
|
namespace App\Filament\Resources;
|
||||||
|
|
||||||
|
use App\Enums\ShippingType;
|
||||||
use App\Filament\Resources\ShippingEntryResource\Pages;
|
use App\Filament\Resources\ShippingEntryResource\Pages;
|
||||||
use App\Models\ShippingEntry;
|
use App\Models\ShippingEntry;
|
||||||
|
use Filament\Forms\Components\Fieldset;
|
||||||
|
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\Components\ToggleButtons;
|
||||||
use Filament\Forms\Form;
|
use Filament\Forms\Form;
|
||||||
use Filament\Resources\Resource;
|
use Filament\Resources\Resource;
|
||||||
|
use Filament\Support\Enums\IconPosition;
|
||||||
use Filament\Tables;
|
use Filament\Tables;
|
||||||
|
use Filament\Tables\Columns\TextColumn;
|
||||||
|
use Filament\Tables\Grouping\Group;
|
||||||
use Filament\Tables\Table;
|
use Filament\Tables\Table;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
class ShippingEntryResource extends Resource
|
class ShippingEntryResource extends Resource
|
||||||
{
|
{
|
||||||
@ -23,7 +35,65 @@ public static function form(Form $form): Form
|
|||||||
{
|
{
|
||||||
return $form
|
return $form
|
||||||
->schema([
|
->schema([
|
||||||
//
|
Section::make([
|
||||||
|
Fieldset::make('Primary information')
|
||||||
|
->schema([
|
||||||
|
Select::make('customer')
|
||||||
|
->relationship('customer', 'company_name')
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
|
||||||
|
ToggleButtons::make('shipping_type')
|
||||||
|
->options(ShippingType::class)
|
||||||
|
->inline()
|
||||||
|
->required(),
|
||||||
|
|
||||||
|
TextInput::make('courier')
|
||||||
|
->placeholder('UPS, Purolator...'),
|
||||||
|
]),
|
||||||
|
|
||||||
|
Split::make([
|
||||||
|
Fieldset::make('Account Details')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('account_title')
|
||||||
|
->label('Title')
|
||||||
|
->prefixIcon('lucide-folder-pen')
|
||||||
|
->placeholder('What is this account used for?')
|
||||||
|
->columnSpan(2),
|
||||||
|
TextInput::make('account_url')
|
||||||
|
->label('URL')
|
||||||
|
->prefixIcon('lucide-globe')
|
||||||
|
->placeholder('Shipping website')
|
||||||
|
->url()
|
||||||
|
->columnSpan(2),
|
||||||
|
TextInput::make('account_username')
|
||||||
|
->label('Username')
|
||||||
|
->prefixIcon('lucide-circle-user')
|
||||||
|
->placeholder('...'),
|
||||||
|
TextInput::make('account_password')
|
||||||
|
->label('Password')
|
||||||
|
->prefixIcon('lucide-key-round')
|
||||||
|
->placeholder('...'),
|
||||||
|
])->columnSpan(1),
|
||||||
|
|
||||||
|
Fieldset::make('Shipping Instructions')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('info_needed')
|
||||||
|
->label('Instructions')
|
||||||
|
->prefixIcon('lucide-pencil')
|
||||||
|
->placeholder('Example: put PO on box')
|
||||||
|
->columnSpan(2),
|
||||||
|
TextInput::make('notify')
|
||||||
|
->placeholder('Who to email and CC?')
|
||||||
|
->prefixIcon('lucide-users-round')
|
||||||
|
->columnSpan(2),
|
||||||
|
TextArea::make('notes')
|
||||||
|
->placeholder('Any additional information...')
|
||||||
|
->rows(2)
|
||||||
|
->columnSpan(2),
|
||||||
|
]),
|
||||||
|
])->columnSpan(2),
|
||||||
|
])->columns(2),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,19 +101,24 @@ public static function table(Table $table): Table
|
|||||||
{
|
{
|
||||||
return $table
|
return $table
|
||||||
->columns([
|
->columns([
|
||||||
Tables\Columns\TextColumn::make('customer.company_name')
|
TextColumn::make('shipping_type')
|
||||||
->searchable(),
|
|
||||||
Tables\Columns\TextColumn::make('shipping_type')
|
|
||||||
->label('Type')
|
->label('Type')
|
||||||
->sortable(),
|
->sortable(),
|
||||||
Tables\Columns\TextColumn::make('courier'),
|
TextColumn::make('courier')
|
||||||
// Tables\Columns\TextColumn::make('contact'),
|
->url(fn ($record) => $record->account_url ?? null, shouldOpenInNewTab: true)
|
||||||
Tables\Columns\TextColumn::make('account_title'),
|
->icon(fn ($record) => $record->account_url ? 'lucide-external-link' : null)
|
||||||
// Tables\Columns\TextColumn::make('account_username'),
|
->iconPosition(IconPosition::After)
|
||||||
// Tables\Columns\TextColumn::make('account_password'),
|
->searchable(query: function (Builder $query, $search) {
|
||||||
Tables\Columns\TextColumn::make('info_needed'),
|
return $query
|
||||||
Tables\Columns\TextColumn::make('notify'),
|
->where('courier', 'like', "%{$search}%")
|
||||||
|
->orWhereHas('customer', function (Builder $query) use ($search) {
|
||||||
|
return $query->where('company_name', 'like', "%{$search}%");
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
|
TextColumn::make('account_title'),
|
||||||
|
TextColumn::make('info_needed'),
|
||||||
|
TextColumn::make('notify'),
|
||||||
])
|
])
|
||||||
->filters([
|
->filters([
|
||||||
//
|
//
|
||||||
@ -55,11 +130,11 @@ public static function table(Table $table): Table
|
|||||||
// Tables\Actions\BulkActionGroup::make([
|
// Tables\Actions\BulkActionGroup::make([
|
||||||
// Tables\Actions\DeleteBulkAction::make(),
|
// Tables\Actions\DeleteBulkAction::make(),
|
||||||
// ]),
|
// ]),
|
||||||
]);
|
])
|
||||||
// ->defaultGroup(
|
->defaultGroup(
|
||||||
// Group::make('customer.company_name')
|
Group::make('customer.company_name')
|
||||||
// ->titlePrefixedWithLabel(false)
|
->titlePrefixedWithLabel(false)
|
||||||
// );
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getRelations(): array
|
public static function getRelations(): array
|
||||||
|
@ -24,6 +24,7 @@ class ShippingEntry extends Model
|
|||||||
'courier',
|
'courier',
|
||||||
'contact',
|
'contact',
|
||||||
'account_title',
|
'account_title',
|
||||||
|
'account_url',
|
||||||
'account_username',
|
'account_username',
|
||||||
'account_password',
|
'account_password',
|
||||||
'info_needed',
|
'info_needed',
|
||||||
|
@ -18,6 +18,7 @@ public function definition(): array
|
|||||||
'courier' => $this->faker->randomElement(['UPS', 'Purolator', 'FreightCom', 'E-Shipper', 'ACE']),
|
'courier' => $this->faker->randomElement(['UPS', 'Purolator', 'FreightCom', 'E-Shipper', 'ACE']),
|
||||||
'contact' => $this->faker->randomElement(['courier.com', '+1 604 123 4567']),
|
'contact' => $this->faker->randomElement(['courier.com', '+1 604 123 4567']),
|
||||||
'account_title' => $this->faker->word,
|
'account_title' => $this->faker->word,
|
||||||
|
'account_url' => 'https://www.example.com',
|
||||||
'account_username' => 'username',
|
'account_username' => 'username',
|
||||||
'account_password' => 'password',
|
'account_password' => 'password',
|
||||||
'info_needed' => $this->faker->words(3, true),
|
'info_needed' => $this->faker->words(3, true),
|
||||||
|
@ -15,6 +15,7 @@ public function up(): void
|
|||||||
$table->string('courier')->nullable();
|
$table->string('courier')->nullable();
|
||||||
$table->string('contact')->nullable();
|
$table->string('contact')->nullable();
|
||||||
$table->string('account_title')->nullable();
|
$table->string('account_title')->nullable();
|
||||||
|
$table->string('account_url')->nullable();
|
||||||
$table->string('account_username')->nullable();
|
$table->string('account_username')->nullable();
|
||||||
$table->string('account_password')->nullable();
|
$table->string('account_password')->nullable();
|
||||||
$table->string('info_needed')->nullable();
|
$table->string('info_needed')->nullable();
|
||||||
|
@ -9,17 +9,23 @@
|
|||||||
use App\Models\Contact;
|
use App\Models\Contact;
|
||||||
use App\Models\Customer;
|
use App\Models\Customer;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
|
use App\Models\OrderProduct;
|
||||||
|
use App\Models\ProductService;
|
||||||
|
use App\Models\ProductSize;
|
||||||
|
use App\Models\ServiceFile;
|
||||||
use App\Models\ServiceType;
|
use App\Models\ServiceType;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
|
||||||
use function Pest\Livewire\livewire;
|
use function Pest\Livewire\livewire;
|
||||||
|
|
||||||
it('can create an order and save it to the database', function () {
|
it('can create an order and all associated models and save it to the database', function () {
|
||||||
$type = fake()->randomElement(OrderType::cases());
|
$type = fake()->randomElement(OrderType::cases());
|
||||||
$status = fake()->randomElement(OrderStatus::cases());
|
$status = fake()->randomElement(OrderStatus::cases());
|
||||||
$customer = Customer::factory()->create();
|
$customer = Customer::factory()->create();
|
||||||
$contact = Contact::factory()->for($customer)->create();
|
$contact = Contact::factory()->for($customer)->create();
|
||||||
$attributes = array_map(fn ($case) => $case->value, OrderAttributes::cases());
|
$attributes = array_map(fn ($case) => $case->value, OrderAttributes::cases());
|
||||||
|
$orderDate = today();
|
||||||
|
$dueDate = today()->addDays(10);
|
||||||
|
|
||||||
$serviceTypes = ServiceType::factory()->count(2)->create();
|
$serviceTypes = ServiceType::factory()->count(2)->create();
|
||||||
|
|
||||||
@ -31,8 +37,8 @@
|
|||||||
'customer_id' => $customer->id,
|
'customer_id' => $customer->id,
|
||||||
'contact_id' => $contact->id,
|
'contact_id' => $contact->id,
|
||||||
'customer_po' => 'Customer PO name here',
|
'customer_po' => 'Customer PO name here',
|
||||||
'order_date' => today(),
|
'order_date' => $orderDate,
|
||||||
'due_date' => today()->addDays(10),
|
'due_date' => $dueDate,
|
||||||
'notes' => 'Notes go here! Here\'s the notes!',
|
'notes' => 'Notes go here! Here\'s the notes!',
|
||||||
'pre_production' => '1',
|
'pre_production' => '1',
|
||||||
'printed' => '1',
|
'printed' => '1',
|
||||||
@ -54,7 +60,7 @@
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'sku' => 'sku 2',
|
'sku' => 'sku 2',
|
||||||
'product_name' => 'alsotest',
|
'product_name' => 'also test',
|
||||||
'color' => 'white',
|
'color' => 'white',
|
||||||
'xs' => '9',
|
'xs' => '9',
|
||||||
's' => '10',
|
's' => '10',
|
||||||
@ -102,9 +108,180 @@
|
|||||||
->assertHasNoErrors();
|
->assertHasNoErrors();
|
||||||
|
|
||||||
$order = Order::first();
|
$order = Order::first();
|
||||||
|
|
||||||
$this->assertNotNull($order);
|
$this->assertNotNull($order);
|
||||||
|
$this->assertSame(
|
||||||
|
[
|
||||||
|
$order->id,
|
||||||
|
$order->customer_id,
|
||||||
|
$order->contact_id,
|
||||||
|
$order->internal_po,
|
||||||
|
$order->customer_po,
|
||||||
|
$order->invoice_id,
|
||||||
|
$order->order_date,
|
||||||
|
$order->order_type,
|
||||||
|
$order->status,
|
||||||
|
$order->due_date,
|
||||||
|
$order->notes,
|
||||||
|
$order->rush,
|
||||||
|
$order->repeat,
|
||||||
|
$order->new_art,
|
||||||
|
$order->event,
|
||||||
|
$order->digitizing,
|
||||||
|
$order->garments,
|
||||||
|
$order->supplied_file,
|
||||||
|
$order->printed,
|
||||||
|
$order->pre_production,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
$customer->id,
|
||||||
|
$contact->id,
|
||||||
|
'TN24-0001',
|
||||||
|
'Customer PO name here',
|
||||||
|
null,
|
||||||
|
$orderDate->format('Y-m-d'),
|
||||||
|
$type,
|
||||||
|
$status,
|
||||||
|
$dueDate->format('Y-m-d'),
|
||||||
|
'Notes go here! Here\'s the notes!',
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
]);
|
||||||
|
|
||||||
$this->assertSame($order->customer_id, $formData['customer_id']);
|
// Order Products
|
||||||
|
$orderProducts = OrderProduct::all();
|
||||||
|
$this->assertNotNull($orderProducts);
|
||||||
|
$this->assertEquals(2, $orderProducts->count());
|
||||||
|
$this->assertEquals(
|
||||||
|
[
|
||||||
|
$orderProducts[0]->id,
|
||||||
|
$orderProducts[0]->sku,
|
||||||
|
$orderProducts[0]->product_name,
|
||||||
|
$orderProducts[0]->color,
|
||||||
|
$orderProducts[0]->order_id,
|
||||||
|
|
||||||
|
$orderProducts[1]->id,
|
||||||
|
$orderProducts[1]->sku,
|
||||||
|
$orderProducts[1]->product_name,
|
||||||
|
$orderProducts[1]->color,
|
||||||
|
$orderProducts[1]->order_id,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
'sku 1',
|
||||||
|
'test',
|
||||||
|
'black',
|
||||||
|
'1',
|
||||||
|
|
||||||
|
2,
|
||||||
|
'sku 2',
|
||||||
|
'also test',
|
||||||
|
'white',
|
||||||
|
'1',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Product Services
|
||||||
|
$productServices = ProductService::all();
|
||||||
|
$this->assertNotNull($productServices);
|
||||||
|
$this->assertEquals(2, $productServices->count());
|
||||||
|
$this->assertEquals(
|
||||||
|
[
|
||||||
|
$productServices[0]->id,
|
||||||
|
$productServices[0]->order_id,
|
||||||
|
$productServices[0]->service_file_id,
|
||||||
|
$productServices[0]->service_type_id,
|
||||||
|
$productServices[0]->placement,
|
||||||
|
$productServices[0]->amount,
|
||||||
|
$productServices[0]->amount_price,
|
||||||
|
$productServices[0]->notes,
|
||||||
|
|
||||||
|
$productServices[1]->id,
|
||||||
|
$productServices[1]->order_id,
|
||||||
|
$productServices[1]->service_file_id,
|
||||||
|
$productServices[1]->service_type_id,
|
||||||
|
$productServices[1]->placement,
|
||||||
|
$productServices[1]->amount,
|
||||||
|
$productServices[1]->amount_price,
|
||||||
|
$productServices[1]->notes,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
$serviceTypes[0]->id,
|
||||||
|
'C/F',
|
||||||
|
'3',
|
||||||
|
'4',
|
||||||
|
'HERE\'S SOME NOTES, ALL HANDWRITTEN BY ME.',
|
||||||
|
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
$serviceTypes[1]->id,
|
||||||
|
'F/B',
|
||||||
|
'8',
|
||||||
|
'9',
|
||||||
|
'HERE\'S EVEN MORE NOTES, STILL HANDWRITTEN BY ME.',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Service Files
|
||||||
|
$serviceFiles = ServiceFile::all();
|
||||||
|
$this->assertNotNull($serviceFiles);
|
||||||
|
$this->assertEquals(2, $serviceFiles->count());
|
||||||
|
$this->assertEquals(
|
||||||
|
[
|
||||||
|
$serviceFiles[0]->id,
|
||||||
|
$serviceFiles[0]->code,
|
||||||
|
$serviceFiles[0]->name,
|
||||||
|
$serviceFiles[0]->width,
|
||||||
|
$serviceFiles[0]->height,
|
||||||
|
$serviceFiles[0]->setup_number,
|
||||||
|
|
||||||
|
$serviceFiles[1]->id,
|
||||||
|
$serviceFiles[1]->code,
|
||||||
|
$serviceFiles[1]->name,
|
||||||
|
$serviceFiles[1]->width,
|
||||||
|
$serviceFiles[1]->height,
|
||||||
|
$serviceFiles[1]->setup_number,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
'A1234',
|
||||||
|
'LOGO NAME 1',
|
||||||
|
'1.00',
|
||||||
|
'2.00',
|
||||||
|
1,
|
||||||
|
|
||||||
|
2,
|
||||||
|
'B5678',
|
||||||
|
'LOGO NAME 2',
|
||||||
|
'6.00',
|
||||||
|
'7.00',
|
||||||
|
5,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Product Sizes
|
||||||
|
$productSizes = ProductSize::all();
|
||||||
|
$this->assertNotNull($productSizes);
|
||||||
|
$this->assertEquals(16, $productSizes->count());
|
||||||
|
|
||||||
|
$sizes = ['xs', 's', 'm', 'l', 'xl', '2xl', '3xl', 'osfa', 'xs', 's', 'm', 'l', 'xl', '2xl', '3xl', 'osfa'];
|
||||||
|
|
||||||
|
for ($i = 0; $i < $productSizes->count(); $i++) {
|
||||||
|
$this->assertSame($productSizes[$i]->id, $i + 1);
|
||||||
|
$this->assertEquals($productSizes[$i]->order_product_id, $i > 7 ? '2' : '1');
|
||||||
|
$this->assertEquals($productSizes[$i]->amount, $i + 1);
|
||||||
|
$this->assertEquals($productSizes[$i]->size, $sizes[$i]);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user