diff --git a/.cursor/skills/abshode-domain-lookup/learned-notes.md b/.cursor/skills/abshode-domain-lookup/learned-notes.md index 3ec0aa6..7080ea5 100644 --- a/.cursor/skills/abshode-domain-lookup/learned-notes.md +++ b/.cursor/skills/abshode-domain-lookup/learned-notes.md @@ -19,3 +19,4 @@ - 2026-09-12 | انقضای کارت هدیه | `GiftCardController::validateGiftExpiryDate` + `GiftCardEditorFormBody` | تاریخ قبل از امروز → ۴۰۰ / خطای فرم؛ امروز مجاز - 2026-09-09 | رمز ادمین ≠ لاگین اپ | `Customer::setPasswordAttribute` + `AuthController` + `updateAdmin` | قبل از هش/لاگین ارقام فارسی→انگلیسی؛ jwt hash=false؛ آنلاین فقط password غیرخالی بفرست - 2026-10-20 | دسترسی صفحات مدیر | `users.page_access` + `AdminPageAccess` + ادمین `adminPageAccess.ts` / ویرایش مدیران | null=کامل؛ درخت مشاهده/ویرایش/حذف؛ ورود=اولین صفحه مجاز؛ منوی ممنوع=«شما به این صفحه دسترسی ندارید» +- 2026-10-20 | ویرایش/حذف کارت هدیه | `GiftCardController::update/destroy` + `giftCards/components/table.vue` | PUT/DELETE `/admin/giftcard/{id}`؛ کارت استفاده‌شده حذف نمی‌شود و مقدار/تعدادش عوض نمی‌شود diff --git a/app/Http/Controllers/Admin/GiftCardController.php b/app/Http/Controllers/Admin/GiftCardController.php index ebda3e8..170e4d8 100644 --- a/app/Http/Controllers/Admin/GiftCardController.php +++ b/app/Http/Controllers/Admin/GiftCardController.php @@ -14,6 +14,7 @@ use Rooyesh\Wallet\interfaces\TransactionInterface; use Rooyesh\Wallet\interfaces\WalletInterface; use App\Services\ConfigService; use App\Services\PargarSyncService; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; @@ -767,6 +768,162 @@ class GiftCardController extends Controller return $giftcode; } + public function update(Request $request, $id) + { + $user = auth()->user(); + if (! $user) { + throw new UnprocessableEntityHttpException('auth failed!'); + } + + $gift = GiftCard::with('giftcardcodes')->findOrFail($id); + $count = (int) $request->count; + $amount = $request->amount; + if ((! is_numeric($request->count) || $count < 1) || (! is_numeric($amount) || $amount <= 0)) { + return response()->json(['message' => 'تعداد یا مقدار را چک کنید!'], 400); + } + + $expiryError = $this->validateGiftExpiryDate($request->expiry_date); + if ($expiryError !== null) { + return response()->json(['message' => $expiryError], 400); + } + + $unit = (int) $request->unit; + if (! in_array($unit, [1, 2, 3], true)) { + return response()->json(['message' => 'نوع کارت هدیه نامعتبر است.'], 400); + } + + try { + $customer = $request->filled('customer_id') + ? $this->resolveGiftCardCustomerForCreate($request) + : null; + } catch (UnprocessableEntityHttpException $e) { + return response()->json(['message' => $e->getMessage()], 400); + } + + $requestedCustomer = $customer?->id ? (int) $customer->id : null; + $currentCustomer = $gift->customer_id ? (int) $gift->customer_id : null; + $structuralChange = $count !== (int) $gift->count + || abs((float) $amount - (float) $gift->amount) > 0.0001 + || $unit !== (int) $gift->unit + || $requestedCustomer !== $currentCustomer; + + if ($this->giftCardIsUsed($gift) && $structuralChange) { + return response()->json([ + 'message' => 'این کارت استفاده شده است؛ فقط توضیحات، تاریخ انقضا و نمایش در اپ قابل ویرایش است.', + ], 400); + } + + $unitAmount = $unit === 3 ? $amount / 100 : $amount; + + DB::transaction(function () use ($gift, $request, $customer, $count, $amount, $unit, $unitAmount, $structuralChange) { + $gift->description = $request->description; + $gift->expiry_date = $request->expiry_date; + if (Schema::hasColumn('giftcards', 'show_in_app')) { + $gift->show_in_app = $customer ? 0 : ($request->boolean('show_in_app') ? 1 : 0); + } + + if (! $structuralChange) { + $gift->save(); + GiftCardCodes::where('giftcard_id', $gift->id) + ->where('sts', '!=', 2) + ->update([ + 'expiry_date' => $request->expiry_date, + 'updated_at' => now(), + ]); + + return; + } + + $gift->customer_id = $customer?->id; + $gift->mobile = $customer?->mobile; + $gift->name = $customer?->name; + $gift->count = $count; + $gift->amount = $unitAmount; + $gift->unit = $unit; + $gift->total = $unit === 3 ? null : $count * $amount; + $gift->save(); + + $this->syncUnusedGiftCodes($gift, $count, $unit, $unitAmount, $request->expiry_date); + }); + + return response()->json($gift->fresh(['giftcardcodes', 'customer'])); + } + + public function destroy($id) + { + $user = auth()->user(); + if (! $user) { + throw new UnprocessableEntityHttpException('auth failed!'); + } + + $gift = GiftCard::with('giftcardcodes')->findOrFail($id); + if ($this->giftCardIsUsed($gift)) { + return response()->json(['message' => 'این کارت هدیه استفاده شده و قابل حذف نیست.'], 400); + } + + DB::transaction(function () use ($gift) { + GiftCardCodes::where('giftcard_id', $gift->id)->delete(); + $gift->delete(); + }); + + return response()->json(true); + } + + private function giftCardIsUsed(GiftCard $gift): bool + { + if ((int) $gift->used_count > 0) { + return true; + } + + return $gift->giftcardcodes->contains(function ($code) { + return (int) $code->sts === 2 || ! empty($code->used_at); + }); + } + + private function syncUnusedGiftCodes(GiftCard $gift, int $count, int $unit, $unitAmount, $expiryDate): void + { + $existing = GiftCardCodes::where('giftcard_id', $gift->id)->orderBy('id')->get(); + $current = $existing->count(); + + if ($count < $current) { + $removeIds = $existing->slice($count)->pluck('id'); + GiftCardCodes::whereIn('id', $removeIds)->delete(); + } elseif ($count > $current) { + $rows = []; + for ($i = 0; $i < $count - $current; $i++) { + do { + $uniqueCode = strtoupper(bin2hex(random_bytes(4))); + } while (GiftCardCodes::where('code', $uniqueCode)->exists()); + + $rows[] = [ + 'giftcard_id' => $gift->id, + 'use_once' => $gift->use_once ? 1 : 0, + 'code' => $uniqueCode, + 'sts' => 1, + 'unit' => $unit, + 'amount' => $unitAmount, + 'expiry_date' => $expiryDate, + 'created_at' => now(), + 'updated_at' => now(), + ]; + } + if ($rows !== []) { + GiftCardCodes::insert($rows); + } + } + + GiftCardCodes::where('giftcard_id', $gift->id)->update([ + 'unit' => $unit, + 'amount' => $unitAmount, + 'expiry_date' => $expiryDate, + 'updated_at' => now(), + ]); + + $firstCode = GiftCardCodes::where('giftcard_id', $gift->id)->orderBy('id')->value('code'); + $gift->unique_code = $count === 1 ? $firstCode : null; + $gift->save(); + } + public function table(Request $request) { $user = auth()->user(); diff --git a/routes/admin.php b/routes/admin.php index 156318f..64e319c 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -329,6 +329,8 @@ Route::middleware(['auth:user', 'admin.page'])->group(function (){ //Giftcard Route::post('giftcard/generate/', [GiftCardController::class, 'redeem']); Route::post('giftcard/table/', [GiftCardController::class, 'table']); + Route::put('giftcard/{id}', [GiftCardController::class, 'update']); + Route::delete('giftcard/{id}', [GiftCardController::class, 'destroy']); Route::get('categories', [CategoryController::class, 'index']); Route::post('categories', [CategoryController::class, 'store']);