Skip to content

Commit 14891ec

Browse files
Merge pull request #107 from khalidmaquilang/feature/si-120-move-sky
SI-120 | Feature | combine sku and name in product
2 parents 98a3a48 + 848e01c commit 14891ec

File tree

7 files changed

+217
-10
lines changed

7 files changed

+217
-10
lines changed

app/Filament/Resources/PurchaseOrderResource.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,20 +42,17 @@ public static function form(Form $form): Form
4242
->relationship()
4343
->addActionLabel('Click to add more products')
4444
->headers([
45-
Header::make('sku')
46-
->label('SKU'),
4745
Header::make('Product Name'),
4846
Header::make('Quantity'),
4947
Header::make('Unit Cost'),
5048
Header::make('Total Cost'),
5149
])
5250
->schema([
53-
Forms\Components\TextInput::make('sku')
54-
->readOnly(),
51+
Forms\Components\Hidden::make('sku'),
5552
Forms\Components\Hidden::make('unit_cost'),
5653
Forms\Components\Hidden::make('name'),
5754
Forms\Components\Select::make('product_id')
58-
->relationship('product', 'name')
55+
->relationship('product', 'sku_name_format')
5956
->live()
6057
->afterStateUpdated(function ($state, Forms\Set $set) {
6158
if (empty($state)) {
@@ -71,6 +68,7 @@ public static function form(Form $form): Form
7168
$product = Product::find($state);
7269
$set('sku', $product->sku);
7370
$set('name', $product->name);
71+
$set('quantity', '');
7472
$set('unit_cost', $product->purchase_price);
7573
$set('formatted_unit_cost', number_format($product->purchase_price, 2));
7674
})
@@ -157,6 +155,7 @@ function ($component) {
157155
Forms\Components\TextInput::make('paid_amount')
158156
->suffix($currency)
159157
->required()
158+
->default(0)
160159
->minValue(0)
161160
->maxValue(fn ($get) => floatval(str_replace(',', '', $get('total_amount'))) ?? 0)
162161
->numeric(),

app/Filament/Resources/SaleResource.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,21 +54,18 @@ public static function form(Form $form): Form
5454
->relationship()
5555
->addActionLabel('Click to add more products')
5656
->headers([
57-
Header::make('sku')
58-
->label('SKU'),
5957
Header::make('Product Name'),
6058
Header::make('Current Stock'),
6159
Header::make('Quantity'),
6260
Header::make('Unit Cost'),
6361
Header::make('Total Cost'),
6462
])
6563
->schema([
66-
Forms\Components\TextInput::make('sku')
67-
->readOnly(),
64+
Forms\Components\Hidden::make('sku'),
6865
Forms\Components\Hidden::make('name'),
6966
Forms\Components\Hidden::make('unit_cost'),
7067
Forms\Components\Select::make('product_id')
71-
->relationship('product', 'name')
68+
->relationship('product', 'sku_name_format')
7269
->lazy()
7370
->afterStateUpdated(function ($state, Forms\Set $set) {
7471
if (empty($state)) {
@@ -85,6 +82,7 @@ public static function form(Form $form): Form
8582
$product = Product::find($state);
8683
$set('sku', $product->sku);
8784
$set('name', $product->name);
85+
$set('quantity', '');
8886
$set('unit_cost', $product->selling_price);
8987
$set('formatted_unit_cost', number_format($product->selling_price, 2));
9088
$set('current_stock', $product->current_stock);

app/Models/GoodsReceipt.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,23 @@ class GoodsReceipt extends Model
1212
{
1313
use HasFactory, SerialGenerationTrait, TenantTrait;
1414

15+
/**
16+
* @var string[]
17+
*/
18+
protected $fillable = [
19+
'company_id',
20+
'grn_code',
21+
'purchase_order_id',
22+
'user_id',
23+
'received_date',
24+
'sku',
25+
'name',
26+
'quantity',
27+
'unit_cost',
28+
'product_id',
29+
'notes',
30+
];
31+
1532
/**
1633
* @var string[]
1734
*/

app/Models/Product.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ class Product extends Model
1818
{
1919
use HasFactory, SoftDeletes, TenantTrait;
2020

21+
protected $fillable = [
22+
'company_id',
23+
'category_id',
24+
'sku',
25+
'name',
26+
'purchase_price',
27+
'selling_price',
28+
'reorder_point',
29+
'last_notified_at',
30+
'description',
31+
];
32+
2133
/**
2234
* @var string[]
2335
*/

app/Models/PurchaseOrder.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ class PurchaseOrder extends Model
1515
{
1616
use HasFactory, SerialGenerationTrait, SoftDeletes, TenantTrait;
1717

18+
/**
19+
* @var string[]
20+
*/
1821
protected $fillable = [
1922
'company_id',
2023
'purchase_code',
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\DB;
6+
use Illuminate\Support\Facades\Schema;
7+
8+
return new class extends Migration
9+
{
10+
/**
11+
* Run the migrations.
12+
*/
13+
public function up(): void
14+
{
15+
Schema::table('products', function (Blueprint $table) {
16+
$connectionName = config('database.default');
17+
$connection = DB::connection($connectionName);
18+
19+
if ($connection->getDriverName() === 'sqlite') {
20+
$table->string('sku_name_format')->virtualAs("sku || ' - ' || name")->after('name');
21+
} else {
22+
$table->string('sku_name_format')->virtualAs("concat(sku, ' - ', name)")->after('name');
23+
}
24+
});
25+
}
26+
27+
/**
28+
* Reverse the migrations.
29+
*/
30+
public function down(): void
31+
{
32+
Schema::table('products', function (Blueprint $table) {
33+
$table->dropColumn('sku_name_format');
34+
});
35+
}
36+
};
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<?php
2+
3+
namespace Tests\Feature\PurchaseOrder;
4+
5+
use App\Filament\Resources\PurchaseOrderResource;
6+
use App\Models\Product;
7+
use App\Models\PurchaseOrder;
8+
use App\Models\PurchaseOrderItem;
9+
use Carbon\Carbon;
10+
use Illuminate\Foundation\Testing\RefreshDatabase;
11+
use Livewire\Livewire;
12+
use Tests\TestCase;
13+
14+
class CreatePurchaseOrderTest extends TestCase
15+
{
16+
use RefreshDatabase;
17+
18+
/**
19+
* @return void
20+
*/
21+
public function test_can_access_create_purchase_order(): void
22+
{
23+
$this->login(['create_purchase::order', 'view_any_purchase::order']);
24+
25+
$this->get(PurchaseOrderResource::getUrl('create'))
26+
->assertSuccessful();
27+
}
28+
29+
/**
30+
* @return void
31+
*/
32+
public function test_cant_access_create_purchase_order_with_wrong_permission(): void
33+
{
34+
$this->login(['create_something']);
35+
36+
$this->get(PurchaseOrderResource::getUrl('create'))
37+
->assertForbidden();
38+
}
39+
40+
/**
41+
* @return void
42+
*/
43+
public function test_can_create_purchase_order(): void
44+
{
45+
$user = $this->login(['create_purchase::order', 'view_any_purchase::order']);
46+
47+
$purchaseOrder = PurchaseOrder::factory()->make([
48+
'company_id' => $this->company->id,
49+
'user_id' => $user->id,
50+
'status' => 'pending',
51+
])->toArray();
52+
$product = Product::factory()->create(['purchase_price' => 100]);
53+
54+
$items = [
55+
[
56+
'product_id' => $product->id,
57+
'quantity' => 1,
58+
],
59+
];
60+
61+
Livewire::test(PurchaseOrderResource\Pages\CreatePurchaseOrder::class)
62+
->set('data.purchaseOrderItems', null)
63+
->fillForm(array_merge($purchaseOrder, ['purchaseOrderItems' => $items, 'paid_amount' => 1]))
64+
->call('create')
65+
->assertHasNoFormErrors();
66+
67+
$this->assertDatabaseHas('purchase_orders', [
68+
'company_id' => $purchaseOrder['company_id'],
69+
'order_date' => (new Carbon($purchaseOrder['order_date']))->startOfDay()->toDateTimeString(),
70+
'total_amount' => $product->purchase_price,
71+
'paid_amount' => 1,
72+
]);
73+
74+
$purchaseOrder = PurchaseOrder::first();
75+
$this->assertDatabaseHas('purchase_order_items', [
76+
'purchase_order_id' => $purchaseOrder->id,
77+
'sku' => $product->sku,
78+
'product_id' => $product->id,
79+
]);
80+
}
81+
82+
/**
83+
* @return void
84+
*/
85+
public function test_cant_create_purchase_order_with_wrong_permission(): void
86+
{
87+
$this->login(['create_something']);
88+
89+
Livewire::test(PurchaseOrderResource\Pages\CreatePurchaseOrder::class)
90+
->assertForbidden();
91+
}
92+
93+
/**
94+
* @return void
95+
*/
96+
public function test_can_create_goods_receipt_when_purchase_order_is_pending(): void
97+
{
98+
$user = $this->login(['create_purchase::order', 'view_any_purchase::order']);
99+
100+
$purchaseOrder = PurchaseOrder::factory()->create([
101+
'company_id' => $this->company->id,
102+
'user_id' => $user->id,
103+
'status' => 'pending',
104+
]);
105+
106+
$product = Product::factory()->create(['purchase_price' => 100]);
107+
PurchaseOrderItem::factory()->create([
108+
'company_id' => $product->id,
109+
'purchase_order_id' => $purchaseOrder->id,
110+
'product_id' => $product->id,
111+
'quantity' => 1,
112+
'unit_cost' => 1,
113+
'sku' => $product->sku,
114+
'name' => $product->name,
115+
]);
116+
117+
Livewire::test(PurchaseOrderResource\RelationManagers\GoodsReceiptsRelationManager::class, [
118+
'ownerRecord' => $purchaseOrder,
119+
'pageClass' => PurchaseOrderResource\Pages\ViewPurchaseOrder::class,
120+
])->callTableAction('create', null, [
121+
'received_date' => now(),
122+
'product_id' => $product->id,
123+
'quantity' => 1,
124+
])
125+
->assertHasNoTableActionErrors();
126+
127+
$this->assertDatabaseHas('goods_receipts', [
128+
'purchase_order_id' => $purchaseOrder->id,
129+
'user_id' => $purchaseOrder->user_id,
130+
'product_id' => $product->id,
131+
'sku' => $product->sku,
132+
'name' => $product->name,
133+
'quantity' => 1,
134+
'unit_cost' => $product->purchase_price,
135+
]);
136+
137+
$this->assertDatabaseHas('purchase_orders', [
138+
'id' => $purchaseOrder->id,
139+
'status' => 'partially_received',
140+
]);
141+
}
142+
}

0 commit comments

Comments
 (0)