feat: introduce ProductCategoryResource and refactor database migrations by deleting old tables and consolidating transaction schema.
This commit is contained in:
@@ -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
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
+12
-12
@@ -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');
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user