Files
boursecu_server/app/Http/Controllers/Admin/GiftCardController.php
T

611 lines
22 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Customer;
use App\Models\GiftCard;
use App\Models\GiftCardCodes;
use App\DB\Te\TableEngine;
use App\Models\Withdraw;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
use Rooyesh\Wallet\interfaces\TransactionInterface;
use Rooyesh\Wallet\interfaces\WalletInterface;
use App\Services\ConfigService;
class GiftCardController extends Controller
{
public function redeem(Request $request)
{
if (app(ConfigService::class)->isStore()) {
return $this->storeRedeem($request);
}
$user = auth()->user();
$count = $request->count;
$amount = $request->amount;
if(!$user){
throw new UnprocessableEntityHttpException('auth failed!');
}
$codes = [];
if((!is_numeric($count) || $count < 0) || (!is_numeric($amount) || $amount <= 0)){
return response()->json(['message' => 'تعداد کد را چک کنید!'], 400);
}
$customer = Customer::select('id', 'name', 'mobile')->where('mobile', $request->mobile)->first();
$gift = GiftCard::create([
'customer_id' => $customer->id ?? null,
'count' => $count,
'amount' => $amount,
'mobile' => $request->mobile ?? null,
'name' => ($customer ? $customer->name : $request->name) ?? null,
'amount' => $amount,
'total' => $count*$amount,
'sts' => 1,
'unit' => $request->unit,
'expiry_date' => $request->expiry_date,
'created_at' => now(),
'updated_at' => now(),
'description' => $request->description,
]);
for ($i = 0; $i < $count; $i++) {
do {
$unique_code = strtoupper(bin2hex(random_bytes(4)));
} while (GiftCardCodes::where('code', $unique_code)->exists());
$codes[] = [
'giftcard_id' => $gift->id,
'code' => $unique_code,
'sts' => 1,
'unit' => $request->unit,
'amount' => $amount,
'expiry_date' => $request->expiry_date,
'created_at' => now(),
];
}
GiftCardCodes::insert($codes);
return response()->json([
'customer' => $customer ?? null,
'order' => $gift,
'codes' => $gift->giftcardcodes,
'total' => $count*$amount,
]);
}
public function useGiftCard(Request $request){
$user = auth()->user();
if(!$user){
throw new UnprocessableEntityHttpException('auth failed!');
}
if (!app(ConfigService::class)->getBool('has_page_gift_card', false)) {
throw new UnprocessableEntityHttpException('قابلیت کارت هدیه غیرفعال است.');
}
$redeem = $request->code;
$giftcode = GiftCardCodes::where('code', $redeem)->first();
$gift = GiftCard::find($giftcode->giftcard_id);
if(!$giftcode){
return response()->json(['message' => 'کد هدیه یافت نشد!'], 404);
}
//gift order update
$gift = GiftCard::find($giftcode->giftcard_id);
if($gift->used_count+1 === $gift->count){
$gift->sts = 2;
}elseif($gift->expiry_date <= now()){
$gift->sts = 3;
$giftcode->sts = 3;
$giftcode->save();
$gift->save();
return response()->json(['message' => 'کد هدیه منقضی شده است!'], 400);
}
$gift->used_count += 1;
$gift->save();
if($giftcode->sts != 1){
return response()->json(['message' => 'کد هدیه قبلا استفاده شده است!'], 400);
}
//tranaction
if($giftcode->unit === 1){
//add IRR to user wallet
$Withdraw = Withdraw::create([
'customer_id' => auth('customer')->id(),
"cash" => $giftcode->amount,
"note" => "کارت هدیه",
'sts' => 1,
'order_id' => $giftcode->id,
]);
$Withdraw->tracked_number = $giftcode->code; // توکن تراکنش برابر کد گیفت کارت
if ($Withdraw->cash == $giftcode->amount) {
if ($Withdraw->order_id){
$this->verifyOrder($Withdraw->id);
}
$Withdraw->zify_code = $Withdraw->tracked_number;
$Withdraw->tracked_number = $giftcode->id;//gift card id
$Withdraw->sts = 6;
$Withdraw->save();
$wallet_interface_fund = new WalletInterface($user->id, $user->type);
$transaction = new TransactionInterface($wallet_interface_fund, $_inp = [
"cash" => $giftcode->amount,
'expire_at' => now(),
'withdraw_id' => $Withdraw->id,
'active' => true
], 3, false, true);
try {
app(\App\Services\PargarSyncService::class)->queueWalletDocument(
$user,
'cash',
(float) $giftcode->amount,
[
'withdraw_id' => $Withdraw->id,
'note' => 'کارت هدیه',
'source' => 'gift_card',
]
);
} catch (\Throwable $e) {
report($e);
}
}
//set text for sms to customer
$amount = number_format($giftcode->amount);
$message = "$user->name عزیز
کیف پول شما به مقدار $amount ریال
به واسطه کارت هدیه از طرف $gift->name شارژ شد.
قلک طلا";
}elseif ($giftcode->unit === 2){
//add Gold to user wallet
return response()->json(['message'=> 'در دست ساخت👷🏻🚧'], 400);
}
//gift code update
$giftcode->assigned_to = $user->id;
$giftcode->sts = 2;
$giftcode->used_at = now();
$giftcode->save();
$this->Send($user->mobile, $message);
return response()->json([
'message' => 'کد هدیه با موفقیت استفاده شد!',
'code' => $giftcode->code,
'amount' => $giftcode->amount,
'unit' => $giftcode->unit,
]);
}
/**
* لیست کدهای قابل‌استفاده (اختصاصی + عمومی تک‌کد) و تاریخچهٔ مصرف‌شدهٔ مشتری.
*/
public function mine(Request $request)
{
$user = auth()->user();
if (! $user) {
throw new UnprocessableEntityHttpException('auth failed!');
}
if (! app(ConfigService::class)->getBool('has_page_gift_card', false)) {
throw new UnprocessableEntityHttpException('قابلیت کارت هدیه غیرفعال است.');
}
$customerId = (int) $user->id;
$mobile = $user->mobile ?? null;
$available = [];
$seenCodes = [];
$personalGifts = GiftCard::query()
->where(function ($q) use ($customerId, $mobile) {
$q->where('customer_id', $customerId);
if ($mobile) {
$q->orWhere('mobile', $mobile);
}
})
->where(function ($q) {
$q->whereNull('sts')->orWhere('sts', '!=', 3);
})
->where(function ($q) {
$q->whereNull('expiry_date')->orWhere('expiry_date', '>', now());
})
->with(['giftcardcodes' => function ($q) {
$q->where('sts', 1);
}])
->orderByDesc('id')
->get();
foreach ($personalGifts as $gift) {
foreach ($gift->giftcardcodes as $code) {
if ($this->isCodeExpired($code, $gift)) {
continue;
}
if (isset($seenCodes[$code->code])) {
continue;
}
$seenCodes[$code->code] = true;
$available[] = $this->mapCustomerGiftItem($gift, $code, 'personal');
}
}
$publicGifts = GiftCard::query()
->where(function ($q) {
$q->whereNull('customer_id')->orWhere('customer_id', 0);
})
->where(function ($q) {
$q->whereNull('mobile')->orWhere('mobile', '');
})
->where('use_once', 0)
->where(function ($q) {
$q->whereNull('sts')->orWhere('sts', '!=', 3);
})
->where(function ($q) {
$q->whereNull('expiry_date')->orWhere('expiry_date', '>', now());
})
->with('giftcardcodes')
->orderByDesc('id')
->get();
foreach ($publicGifts as $gift) {
if ((int) $gift->count > 0 && (int) $gift->used_count >= (int) $gift->count) {
continue;
}
$codes = $gift->giftcardcodes
->filter(function ($code) use ($gift) {
return (int) $code->sts !== 2
&& (int) $code->sts !== 3
&& ! $this->isCodeExpired($code, $gift);
})
->values();
// عمومی: فقط پویش تک‌کد مشترک (جلوگیری از افشای بچ تصادفی)
if ($codes->count() !== 1 && empty($gift->unique_code)) {
continue;
}
$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 = [];
$historyCodes = GiftCardCodes::query()
->whereNotNull('assigned_to')
->where('assigned_to', '!=', '')
->where(function ($q) use ($customerId) {
$id = (string) $customerId;
$q->where('assigned_to', $customerId)
->orWhere('assigned_to', $id)
->orWhere('assigned_to', '['.$id.']')
->orWhere('assigned_to', 'like', '%"'.$id.'"%')
->orWhere('assigned_to', 'like', '%['.$id.',%')
->orWhere('assigned_to', 'like', '%,'.$id.']%')
->orWhere('assigned_to', 'like', '%,'.$id.',%');
})
->with('giftcard')
->orderByDesc('used_at')
->orderByDesc('updated_at')
->limit(100)
->get();
foreach ($historyCodes as $code) {
$gift = $code->giftcard;
if (! $gift || ! $this->customerAlreadyUsedCode($code, $customerId, $gift)) {
continue;
}
$history[] = $this->mapCustomerGiftItem($gift, $code, $this->resolveCodeScope($gift, $customerId, $mobile));
}
return response()->json([
'available' => $available,
'history' => $history,
]);
}
private function isCodeExpired(GiftCardCodes $code, GiftCard $gift): bool
{
if ($code->expiry_date && $code->expiry_date <= now()) {
return true;
}
if ($gift->expiry_date && $gift->expiry_date <= now()) {
return true;
}
return false;
}
private function customerAlreadyUsedCode(GiftCardCodes $code, int $customerId, GiftCard $gift): bool
{
$assigned = $code->assigned_to;
if ($assigned === null || $assigned === '') {
return false;
}
if ((int) $gift->unit === 3 || (is_string($assigned) && str_starts_with(trim($assigned), '['))) {
$ids = json_decode($assigned, true);
if (! is_array($ids)) {
return false;
}
return in_array($customerId, $ids, false) || in_array((string) $customerId, $ids, false);
}
return (string) $assigned === (string) $customerId;
}
private function resolveCodeScope(GiftCard $gift, int $customerId, ?string $mobile): string
{
if ((int) $gift->customer_id === $customerId) {
return 'personal';
}
if ($mobile && $gift->mobile && (string) $gift->mobile === (string) $mobile) {
return 'personal';
}
return 'public';
}
private function mapCustomerGiftItem(GiftCard $gift, GiftCardCodes $code, string $scope): array
{
$unit = (int) ($code->unit ?? $gift->unit);
return [
'id' => $code->id,
'giftcard_id' => $gift->id,
'code' => $code->code,
'name' => $gift->name,
'description' => $gift->description,
'amount' => $code->amount ?? $gift->amount,
'unit' => $unit,
'kind' => $unit === 3 ? 'discount' : 'gift',
'scope' => $scope,
'sts' => (int) $code->sts,
'expiry_date' => $code->expiry_date ?? $gift->expiry_date,
'used_at' => $code->used_at,
];
}
public function useDiscount(Request $request)
{
if (! app(ConfigService::class)->isStore()) {
return response()->json(['message' => 'این قابلیت فقط برای فروشگاه فعال است'], 403);
}
$result = $this->applyDiscount((string) $request->input('code'), auth('customer')->id());
if (! empty($result['message'])) {
return response()->json(['message' => $result['message']], 400);
}
return response()->json(['amount' => $result['amount']]);
}
public function validateDiscount(Request $request)
{
if (! app(ConfigService::class)->isStore()) {
return response()->json(['message' => 'این قابلیت فقط برای فروشگاه فعال است'], 403);
}
$giftcode = $this->verifyDiscount((string) $request->input('code'));
if (! empty($giftcode['message'])) {
return response()->json(['message' => $giftcode['message']], 400);
}
return response()->json(['giftcard' => $giftcode], 200);
}
private function storeRedeem(Request $request)
{
$user = auth()->user();
$count = $request->count;
$amount = $request->amount;
if (! $user) {
throw new UnprocessableEntityHttpException('auth failed!');
}
if ((! is_numeric($count) || $count < 0) || (! is_numeric($amount) || $amount <= 0)) {
return response()->json(['message' => 'تعداد کد را چک کنید!'], 400);
}
if (isset($request->code) && GiftCardCodes::where('code', $request->code)->where('unit', $request->unit)->exists()) {
return response()->json(['message' => 'کد تکراری میباشد!'], 400);
}
$codes = [];
$unitAmount = $request->unit == 3 ? $amount / 100 : $amount;
if ($request->use_once) {
$gift = GiftCard::create([
'use_once' => $request->use_once ? 1 : 0,
'count' => $count,
'amount' => $unitAmount,
'name' => $request->name,
'total' => $request->unit == 3 ? null : $count * $amount,
'sts' => 1,
'unit' => $request->unit,
'expiry_date' => $request->expiry_date,
'created_at' => now(),
'updated_at' => now(),
'description' => $request->description,
]);
for ($i = 0; $i < $count; $i++) {
do {
$unique_code = strtoupper(bin2hex(random_bytes(4)));
} while (GiftCardCodes::where('code', $unique_code)->exists());
$codes[] = [
'giftcard_id' => $gift->id,
'use_once' => $request->use_once ? 1 : 0,
'code' => $unique_code,
'sts' => 1,
'unit' => $request->unit,
'amount' => $unitAmount,
'expiry_date' => $request->expiry_date,
'created_at' => now(),
];
}
GiftCardCodes::insert($codes);
} else {
do {
$unique_code = strtoupper(bin2hex(random_bytes(4)));
} while (GiftCardCodes::where('code', $unique_code)->exists());
$gift = GiftCard::create([
'use_once' => $request->use_once ? 1 : 0,
'count' => $count,
'unique_code' => ! empty($request->code) ? $request->code : $unique_code,
'amount' => $unitAmount,
'name' => $request->name,
'total' => $request->unit == 3 ? null : $count * $amount,
'sts' => 1,
'unit' => $request->unit,
'expiry_date' => $request->expiry_date,
'created_at' => now(),
'updated_at' => now(),
'description' => $request->description,
]);
GiftCardCodes::insert([
'giftcard_id' => $gift->id,
'use_once' => $request->use_once ? 1 : 0,
'code' => ! empty($request->code) ? $request->code : $unique_code,
'sts' => 1,
'unit' => $request->unit,
'amount' => $unitAmount,
'expiry_date' => $request->expiry_date,
'created_at' => now(),
]);
}
return response()->json([
'order' => $gift,
'codes' => $gift->giftcardcodes,
'total' => $count * $amount,
]);
}
public function applyDiscount(string $code, $customerId): array
{
$giftcode = $this->verifyDiscount($code);
if (! empty($giftcode['message'])) {
return ['message' => $giftcode['message']];
}
$giftcode = GiftCardCodes::where('code', $code)->first();
$gift = GiftCard::find($giftcode->giftcard_id);
$idsArray = json_decode($giftcode->assigned_to, true);
if (! is_array($idsArray)) {
$idsArray = [];
}
$idsArray[] = $customerId;
if ($gift->use_once == 1) {
$giftcode->sts = 2;
}
$giftcode->assigned_to = json_encode($idsArray);
$giftcode->save();
$gift->used_count += 1;
if ($gift->used_count + 1 > $gift->count) {
$gift->sts = 2;
}
$gift->save();
return ['amount' => $giftcode->amount];
}
private function verifyDiscount(string $code)
{
$giftcode = GiftCardCodes::where('code', $code)->first();
if (! $giftcode) {
return ['message' => 'کد تخفیف یافت نشد!'];
}
$gift = GiftCard::find($giftcode->giftcard_id);
$customer_id = auth('customer')->id();
if ($gift->unit !== 3 || $giftcode->unit !== 3) {
return ['message' => 'کد تخفیف صحیح نمیباشد!'];
}
if ($gift->use_once === 0) {
$stored_ids = json_decode($giftcode->assigned_to, true);
if (is_array($stored_ids) && in_array($customer_id, $stored_ids)) {
return ['message' => 'شما قبلا از تخفیف خود استفاده کرده اید!'];
}
} elseif ($gift->use_once === 1) {
if (GiftCardCodes::where('giftcard_id', $gift->id)->where('assigned_to', '['.auth('customer')->id().']')->exists()) {
return ['message' => 'شما قبلا از تخفیف خود استفاده کرده اید!'];
}
}
if ($gift->expiry_date <= now() || $gift->sts === 3) {
$gift->sts = 3;
$giftcode->sts = 3;
$giftcode->save();
$gift->save();
return ['message' => 'کد تخفیف منقضی شده است!'];
}
if ($giftcode->sts === 2) {
return ['message' => 'کد تخفیف قبلا استفاده شده است!'];
}
if ($gift->used_count + 1 > $gift->count) {
return ['message' => 'تعداد استفاده کد تخفیف به پایان رسیده است!'];
}
return $giftcode;
}
public function table(Request $request)
{
$user = auth()->user();
if(!$user){
throw new UnprocessableEntityHttpException('auth failed!');
}
$records = GiftCard::with([
'giftcardcodes',
'giftcardcodes.assignedTo'
]);
TableEngine::create($records, $request->all())
->initSearch([])
->select([
'*', GiftCard::$SELECT_STS_STR
])->export($records);
return response()->json($records);
}
}