From 41851130919918001c6ad12b42b0ac8633d25660 Mon Sep 17 00:00:00 2001 From: Amirmahdi Nourkazemi Date: Thu, 18 Jun 2026 12:46:37 +0330 Subject: [PATCH] feat: add some fields to product --- app/Http/Controllers/ProductController.php | 43 ++++++++++++++++--- app/Models/Product.php | 2 + ...0_add_display_fields_to_products_table.php | 41 ++++++++++++++++++ 3 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 database/migrations/2026_06_18_000000_add_display_fields_to_products_table.php diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index c3d270c..eda99a4 100755 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -21,7 +21,7 @@ public function index(Request $request, $packageName) 'message' => 'package name not found' ], 404); } - $products = $packageName->products; + $products = $packageName->products()->orderBy('sort_order')->orderBy('id')->get(); return $products; } @@ -31,8 +31,14 @@ public function store(Request $request, $packageName) 'title' => 'string|required', 'price' => 'integer|required', 'type' => ['integer', Rule::in(Product::TYPES)], - 'descriptions' => 'array|nullable', - 'descriptions.*' => 'string|max:1000', + 'descriptions' => 'array|nullable', + 'descriptions.*' => 'string|max:1000', + // Display-only text fields (no calculation) + 'discounted_price' => 'string|nullable', + 'daily_price' => 'string|nullable', + 'discount' => 'string|nullable', + 'is_best_seller' => 'boolean|nullable', + 'sort_order' => 'integer|nullable', ]); if (!$packageName = PackageName::with('products')->where('name', $packageName)->first()) { @@ -42,6 +48,11 @@ public function store(Request $request, $packageName) } $product = $packageName->products()->create($data); + + if (!empty($data['is_best_seller'])) { + $this->keepSingleBestSeller($packageName, $product->id); + } + return $product; } @@ -51,8 +62,14 @@ public function update(Request $request, $packageName, $productId) 'title' => 'string|required', 'price' => 'integer|required', 'type' => ['integer', Rule::in(Product::TYPES)], - 'descriptions' => 'array|nullable', - 'descriptions.*' => 'string|max:1000' + 'descriptions' => 'array|nullable', + 'descriptions.*' => 'string|max:1000', + // Display-only text fields (no calculation) + 'discounted_price' => 'string|nullable', + 'daily_price' => 'string|nullable', + 'discount' => 'string|nullable', + 'is_best_seller' => 'boolean|nullable', + 'sort_order' => 'integer|nullable', ]); if (!$packageName = PackageName::with('products')->where('name', $packageName)->first()) { @@ -68,9 +85,25 @@ public function update(Request $request, $packageName, $productId) } $product->update($data); + + if (!empty($data['is_best_seller'])) { + $this->keepSingleBestSeller($packageName, $product->id); + } + return $product; } + /** + * Make sure only one product within a package is flagged as best-seller. + */ + private function keepSingleBestSeller(PackageName $packageName, $keepProductId): void + { + $packageName->products() + ->where('id', '!=', $keepProductId) + ->where('is_best_seller', true) + ->update(['is_best_seller' => false]); + } + public function delete($packageName, $productId) { if (!$packageName = PackageName::with('products')->where('name', $packageName)->first()) { diff --git a/app/Models/Product.php b/app/Models/Product.php index 8cfd723..283a5bc 100755 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -27,6 +27,8 @@ public function users() } protected $casts = [ 'descriptions' => 'array', + 'is_best_seller' => 'boolean', + 'sort_order' => 'integer', ]; diff --git a/database/migrations/2026_06_18_000000_add_display_fields_to_products_table.php b/database/migrations/2026_06_18_000000_add_display_fields_to_products_table.php new file mode 100644 index 0000000..f90a219 --- /dev/null +++ b/database/migrations/2026_06_18_000000_add_display_fields_to_products_table.php @@ -0,0 +1,41 @@ +string('discounted_price')->nullable()->after('descriptions'); // قیمت کلی تخفیف خورده + $table->string('daily_price')->nullable()->after('discounted_price'); // قیمت روزانه + $table->string('discount')->nullable()->after('daily_price'); // تخفیف + // Best-seller flag (only one per package should be active) + $table->boolean('is_best_seller')->default(false)->after('discount'); // پرفروش‌ترین + // Display order (lower = shown higher, 0 is top) + $table->unsignedInteger('sort_order')->default(0)->after('is_best_seller'); // ترتیب + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('products', function (Blueprint $table) { + $table->dropColumn([ + 'discounted_price', + 'daily_price', + 'discount', + 'is_best_seller', + 'sort_order', + ]); + }); + } +};