diff --git a/app/Http/Controllers/Admin/GiftCardController.php b/app/Http/Controllers/Admin/GiftCardController.php index 27b916e..a3b587c 100644 --- a/app/Http/Controllers/Admin/GiftCardController.php +++ b/app/Http/Controllers/Admin/GiftCardController.php @@ -39,7 +39,7 @@ class GiftCardController extends Controller return response()->json(['message' => $expiryError], 400); } - $customer = Customer::select('id', 'name', 'mobile')->where('mobile', $request->mobile)->first(); + $customer = $this->resolveGiftCardCustomerForCreate($request); $gift = $this->createGiftCardWithUniqueCodes($request, $customer); $createdCodes = $gift->giftcardcodes->pluck('code')->all(); @@ -342,6 +342,10 @@ class GiftCardController extends Controller continue; } + if (! $this->isPublicGiftVisibleInApp($gift)) { + continue; + } + $codes = $gift->giftcardcodes ->filter(function ($code) use ($gift) { return (int) $code->sts !== 2 @@ -350,23 +354,16 @@ class GiftCardController extends Controller }) ->values(); - // عمومی: فقط پویش تک‌کد مشترک (جلوگیری از افشای بچ تصادفی) - if ($codes->count() !== 1 && empty($gift->unique_code)) { - continue; + foreach ($codes as $code) { + if ($this->customerAlreadyUsedCode($code, $customerId, $gift)) { + continue; + } + if (isset($seenCodes[$code->code])) { + continue; + } + $seenCodes[$code->code] = true; + $available[] = $this->mapCustomerGiftItem($gift, $code, 'public'); } - - $code = $codes->first(); - if (! $code) { - continue; - } - if ($this->customerAlreadyUsedCode($code, $customerId, $gift)) { - continue; - } - if (isset($seenCodes[$code->code])) { - continue; - } - $seenCodes[$code->code] = true; - $available[] = $this->mapCustomerGiftItem($gift, $code, 'public'); } $history = []; @@ -403,11 +400,55 @@ class GiftCardController extends Controller ]); } + private function resolveGiftCardCustomer(Request $request): ?Customer + { + if ($request->filled('customer_id')) { + return Customer::select('id', 'name', 'mobile')->find((int) $request->customer_id); + } + + if ($request->filled('mobile')) { + return Customer::select('id', 'name', 'mobile')->where('mobile', $request->mobile)->first(); + } + + return null; + } + + /** + * کارت عمومی: show_in_app=1 → در لیست اپ همه؛ ۰ → فقط با وارد کردن دستی کد. + * سازگاری با رکوردهای قبل از ستون show_in_app: تک‌کد مشترک مثل قبل در اپ می‌آید. + */ + private function isPublicGiftVisibleInApp(GiftCard $gift): bool + { + if (! isset($gift->show_in_app)) { + $codesCount = $gift->relationLoaded('giftcardcodes') + ? $gift->giftcardcodes->count() + : $gift->giftcardcodes()->count(); + + return $codesCount === 1 || ! empty($gift->unique_code); + } + + return (int) $gift->show_in_app === 1; + } + + private function resolveGiftCardCustomerForCreate(Request $request): ?Customer + { + $customer = $this->resolveGiftCardCustomer($request); + if ($request->filled('customer_id') && ! $customer) { + throw new UnprocessableEntityHttpException('مشتری انتخاب‌شده یافت نشد!'); + } + + return $customer; + } + /** * یک رکورد giftcards + N کد یکتا در giftcard_codes (نه N رکورد جدا). */ private function createGiftCardWithUniqueCodes(Request $request, ?Customer $customer = null): GiftCard { + if ($customer === null) { + $customer = $this->resolveGiftCardCustomer($request); + } + $count = (int) $request->count; $amount = $request->amount; $unit = (int) $request->unit; @@ -416,6 +457,7 @@ class GiftCardController extends Controller $gift = GiftCard::create([ 'customer_id' => $customer?->id, 'use_once' => $request->use_once ? 1 : 0, + 'show_in_app' => $customer ? 0 : ($request->boolean('show_in_app') ? 1 : 0), 'count' => $count, 'amount' => $unitAmount, 'mobile' => $customer?->mobile ?? $request->mobile ?? null, @@ -453,7 +495,7 @@ class GiftCardController extends Controller $gift->save(); } - return $gift->load('giftcardcodes'); + return $gift->load(['giftcardcodes', 'customer']); } /** @@ -598,7 +640,12 @@ class GiftCardController extends Controller $createUniqueCodes = $request->use_once || $unit === 1 || $unit === 2; if ($createUniqueCodes) { - $gift = $this->createGiftCardWithUniqueCodes($request); + try { + $customer = $this->resolveGiftCardCustomerForCreate($request); + } catch (UnprocessableEntityHttpException $e) { + return response()->json(['message' => $e->getMessage()], 400); + } + $gift = $this->createGiftCardWithUniqueCodes($request, $customer); } else { do { $unique_code = strtoupper(bin2hex(random_bytes(4))); @@ -722,8 +769,9 @@ class GiftCardController extends Controller throw new UnprocessableEntityHttpException('auth failed!'); } $records = GiftCard::with([ + 'customer', 'giftcardcodes', - 'giftcardcodes.assignedTo' + 'giftcardcodes.assignedTo', ]); TableEngine::create($records, $request->all()) ->initSearch([]) diff --git a/app/Models/GiftCard.php b/app/Models/GiftCard.php index f1026b3..abeb630 100644 --- a/app/Models/GiftCard.php +++ b/app/Models/GiftCard.php @@ -4,6 +4,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use App\Models\Customer; use App\Models\GiftCardCodes; class GiftCard extends Model @@ -15,6 +16,7 @@ class GiftCard extends Model protected $fillable = [ 'customer_id', 'use_once', + 'show_in_app', 'count', 'amount', 'total', @@ -33,6 +35,11 @@ class GiftCard extends Model return $this->hasMany(GiftCardCodes::class, 'giftcard_id', 'id'); } + public function customer() + { + return $this->belongsTo(Customer::class, 'customer_id', 'id')->select('id', 'name', 'mobile'); + } + static $STS = [ 1 => "فعال", 2 => "تمام شده", diff --git a/database/migrations/2026_09_21_000001_add_giftcard_show_in_app.php b/database/migrations/2026_09_21_000001_add_giftcard_show_in_app.php new file mode 100644 index 0000000..de48816 --- /dev/null +++ b/database/migrations/2026_09_21_000001_add_giftcard_show_in_app.php @@ -0,0 +1,22 @@ +unsignedTinyInteger('show_in_app')->default(0)->after('use_once'); + }); + } + } + + public function down(): void + { + // ستون ممکن است روی نصب‌های قدیمی استفاده شود؛ drop نمی‌کنیم. + } +}; diff --git a/database/sql/deploy_safe_schema.sql b/database/sql/deploy_safe_schema.sql index 9f9c7a4..37a270e 100644 --- a/database/sql/deploy_safe_schema.sql +++ b/database/sql/deploy_safe_schema.sql @@ -794,6 +794,14 @@ SET @sql = IF( ); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA=@db AND TABLE_NAME='giftcards' AND COLUMN_NAME='show_in_app') = 0, + 'ALTER TABLE `giftcards` ADD COLUMN `show_in_app` TINYINT UNSIGNED NOT NULL DEFAULT 0 AFTER `use_once`', + 'SELECT ''skip giftcards.show_in_app'' AS info' +); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + SET @sql = IF( (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='giftcard_codes' AND COLUMN_NAME='amount') > 0