feat: introduce ProductCategoryResource and refactor database migrations by deleting old tables and consolidating transaction schema.

This commit is contained in:
pbao9
2026-02-18 21:44:31 +07:00
parent 9a2cab4521
commit 75791d6257
12 changed files with 76 additions and 163 deletions
@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Api\Service;
use App\Http\Controllers\Controller;
use App\Http\Resources\Api\Service\ProductCategoryResource;
use App\Http\Resources\Api\Service\ServiceResource;
use App\Models\Product;
use App\Models\ProductCategories;
@@ -63,7 +64,7 @@ class ProductCategoryController extends Controller
return response()->json([
'error' => false,
'message' => 'Lấy dữ liệu thành công',
'data' => $categories,
'data' => ProductCategoryResource::collection($categories),
]);
}
@@ -0,0 +1,26 @@
<?php
namespace App\Http\Resources\Api\Service;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ProductCategoryResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'slug' => $this->slug,
'parent_id' => $this->parent_id,
'is_active' => $this->is_active,
'sort_order' => $this->sort_order,
'type' => $this->type,
'type_label' => $this->type_label,
'children' => $this->when($this->children, function () {
return self::collection($this->children);
}),
];
}
}
+15 -1
View File
@@ -32,7 +32,6 @@ class Product extends Model
'is_unlimited',
'is_active',
'sort_order',
'product_type',
'product_categories_id',
'published_at',
];
@@ -42,8 +41,23 @@ class Product extends Model
'is_unlimited' => 'boolean',
'published_at' => 'date',
'gallery' => 'array',
'product_type' => 'string',
];
protected static function boot()
{
parent::boot();
static::saving(function ($product) {
if ($product->product_categories_id) {
$category = ProductCategories::find($product->product_categories_id);
if ($category && $category->type) {
$product->product_type = $category->type;
}
}
});
}
/**
* Relationship: Product belongs to a Category
*/
+15
View File
@@ -2,6 +2,7 @@
namespace App\Models;
use App\Enums\Product\ProductTypeEnums;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -18,6 +19,7 @@ class ProductCategories extends Model
'parent_id',
'is_active',
'sort_order',
'type',
];
public function parent()
@@ -34,4 +36,17 @@ class ProductCategories extends Model
{
return $this->hasMany(Product::class, 'product_categories_id');
}
public function getTypeLabelAttribute(): ?string
{
if (!$this->type) {
return null;
}
return ProductTypeEnums::tryFrom($this->type)?->label();
}
public static function getTypeOptions(): array
{
return array_map(fn($case) => $case->value, ProductTypeEnums::cases());
}
}
@@ -17,7 +17,7 @@ return new class extends Migration {
$table->foreignId('parent_id')->nullable()
->constrained('product_categories')
->nullOnDelete();
$table->enum('type', ['vps', 'hosting', 'cloud', 'email', 'ssl', 'domain', 'web_design', 'addon'])->nullable();
$table->boolean('is_active')->default(true);
$table->integer('sort_order')->default(0);
@@ -1,49 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('hosting', function (Blueprint $table) {
$table->id()->autoIncrement();
$table->string('name', 255)->nullable();
$table->string('slug')->nullable();
$table->integer('price')->nullable();
$table->integer('price_sale')->nullable();
$table->integer('ram')->default(0)->nullable();
$table->integer('disk')->default(125)->nullable();
$table->integer('cpu')->default(1)->nullable();
$table->integer('gpu')->default(0)->nullable();
$table->integer('ip')->default(0)->nullable();
$table->integer('bandwidth')->default(1000)->nullable();
$table->integer('module_host_id')->nullable()->index();
$table->text('description')->nullable();
$table->string('template', 255)->nullable();
$table->tinyInteger('type_id')->default(0)->index();
$table->integer('group_id')->default(0)->index();
$table->tinyInteger('status')->default(1);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('hosting', function (Blueprint $table) {
$table->dropForeign('group_id');
$table->drop();
});
}
};
@@ -1,45 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
Schema::create('vps', function (Blueprint $table) {
$table->id()->autoIncrement();
$table->string('name', 100)->nullable();
$table->integer('cpu')->default(1);
$table->integer('ram')->default(1);
$table->integer('disk')->default(10);
$table->integer('gpu')->nullable();
$table->text('description')->nullable();
$table->integer('bandwidth')->default(100);
$table->integer('price')->nullable();
$table->integer('price_sale')->nullable();
$table->bigInteger('module_host_id')->default(0)->index();
$table->integer('type_id')->default(0)->index();
$table->integer('group_id')->default(0)->index();
$table->tinyInteger('status')->default(1);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
Schema::dropIfExists('vps');
}
};
@@ -16,6 +16,8 @@ return new class extends Migration {
->constrained('customers')
->cascadeOnDelete();
$table->tinyInteger('status')->default(0)->comment('0: pending, 1: completed, 2: fail');
$table->timestamps();
$table->softDeletes();
});
@@ -7,21 +7,21 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up()
{
Schema::table('customers', function (Blueprint $table) {
$table->softDeletes();
});
// Schema::table('customers', function (Blueprint $table) {
// $table->softDeletes();
// });
Schema::table('invoice', function (Blueprint $table) {
$table->softDeletes();
});
// Schema::table('invoice', function (Blueprint $table) {
// $table->softDeletes();
// });
Schema::table('order', function (Blueprint $table) {
$table->softDeletes();
});
// Schema::table('order', function (Blueprint $table) {
// $table->softDeletes();
// });
Schema::table('transaction', function (Blueprint $table) {
$table->softDeletes();
});
// Schema::table('transaction', function (Blueprint $table) {
// $table->softDeletes();
// });
}
public function down()
@@ -7,9 +7,9 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up()
{
Schema::table('transaction', function (Blueprint $table) {
$table->softDeletes();
});
// Schema::table('transaction', function (Blueprint $table) {
// $table->softDeletes();
// });
}
public function down()
@@ -1,30 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up()
{
Schema::create('transactions', function (Blueprint $table) {
$table->id();
$table->string('trans')->nullable();
$table->integer('amount')->nullable();
$table->foreignId('customer_id')
->constrained('customers')
->cascadeOnDelete();
$table->timestamps();
$table->softDeletes();
});
}
public function down()
{
Schema::table('transactions', function (Blueprint $table) {
$table->dropForeign(['customer_id']);
});
}
};
@@ -1,21 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up()
{
Schema::table('transactions', function (Blueprint $table) {
$table->tinyInteger('status')->default(0)->comment('0: pending, 1: completed, 2: fail')->after('amount');
});
}
public function down()
{
Schema::table('transactions', function (Blueprint $table) {
$table->dropColumn('status');
});
}
};