all customer from pargar fixing 2
This commit is contained in:
@@ -133,11 +133,43 @@ class PargarController extends Controller
|
|||||||
$fullName = trim($item['name']);
|
$fullName = trim($item['name']);
|
||||||
$accountId = (string) $item['code'];
|
$accountId = (string) $item['code'];
|
||||||
|
|
||||||
|
// بدون موبایل ردیف placeholder نساز — باعث ثبتنام تکراری و کیف جدا میشود
|
||||||
|
if ($mobile === '') {
|
||||||
|
$failed++;
|
||||||
|
$errors[] = [
|
||||||
|
'name' => $item['name'],
|
||||||
|
'code' => $item['code'],
|
||||||
|
'error' => 'شماره موبایل خالی است — وارد نشد',
|
||||||
|
];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$existing = Customer::whereNull('deleted_at')
|
$existing = Customer::whereNull('deleted_at')
|
||||||
->where('pargar_account_id', $accountId)
|
->where('pargar_account_id', $accountId)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($existing) {
|
if ($existing) {
|
||||||
|
$changed = false;
|
||||||
|
if (($existing->mobile === null || trim((string) $existing->mobile) === '')) {
|
||||||
|
if (Customer::isMobileTaken($mobile, (int) $existing->id)) {
|
||||||
|
$failed++;
|
||||||
|
$errors[] = [
|
||||||
|
'name' => $item['name'],
|
||||||
|
'code' => $item['code'],
|
||||||
|
'error' => 'شماره موبایل تکراری است',
|
||||||
|
];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$existing->mobile = $mobile;
|
||||||
|
if (empty($existing->password)) {
|
||||||
|
$existing->password = $mobile;
|
||||||
|
}
|
||||||
|
$changed = true;
|
||||||
|
}
|
||||||
|
if ($changed) {
|
||||||
|
$existing->save();
|
||||||
|
app(PargarInboundWalletService::class)->queueWalletSyncAfterResponse((int) $existing->id);
|
||||||
|
}
|
||||||
$success++;
|
$success++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -162,6 +194,7 @@ class PargarController extends Controller
|
|||||||
$byMobile->name = $fullName;
|
$byMobile->name = $fullName;
|
||||||
}
|
}
|
||||||
$byMobile->save();
|
$byMobile->save();
|
||||||
|
app(PargarInboundWalletService::class)->queueWalletSyncAfterResponse((int) $byMobile->id);
|
||||||
$success++;
|
$success++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -190,10 +223,9 @@ class PargarController extends Controller
|
|||||||
$customer->pargar_account_id = $accountId;
|
$customer->pargar_account_id = $accountId;
|
||||||
$customer->referral_id = $this->uniqueReferralId();
|
$customer->referral_id = $this->uniqueReferralId();
|
||||||
$customer->type = 2;
|
$customer->type = 2;
|
||||||
if ($mobile !== '') {
|
$customer->password = $mobile;
|
||||||
$customer->password = $mobile;
|
|
||||||
}
|
|
||||||
$customer->save();
|
$customer->save();
|
||||||
|
app(PargarInboundWalletService::class)->queueWalletSyncAfterResponse((int) $customer->id);
|
||||||
$success++;
|
$success++;
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
$failed++;
|
$failed++;
|
||||||
|
|||||||
@@ -230,6 +230,17 @@ class TahesabController extends Controller
|
|||||||
$fullName = trim($item['name']);
|
$fullName = trim($item['name']);
|
||||||
$code = (int) $item['code'];
|
$code = (int) $item['code'];
|
||||||
|
|
||||||
|
// بدون موبایل ردیف placeholder نساز
|
||||||
|
if ($mobile === '') {
|
||||||
|
$failed++;
|
||||||
|
$errors[] = [
|
||||||
|
'name' => $item['name'],
|
||||||
|
'code' => $item['code'],
|
||||||
|
'error' => 'شماره موبایل خالی است — وارد نشد',
|
||||||
|
];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$existing = Customer::whereNull('deleted_at')->where('moshtari_code', $code)->first();
|
$existing = Customer::whereNull('deleted_at')->where('moshtari_code', $code)->first();
|
||||||
if ($existing) {
|
if ($existing) {
|
||||||
$changed = false;
|
$changed = false;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use App\Models\Customer;
|
|||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Services\ConfigService;
|
use App\Services\ConfigService;
|
||||||
|
use App\Services\PargarInboundWalletService;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
@@ -25,7 +26,8 @@ class AuthController extends Controller
|
|||||||
if ($data['provider'] == 'user') {
|
if ($data['provider'] == 'user') {
|
||||||
$user = User::where('mobile', $request->mobile)->first();
|
$user = User::where('mobile', $request->mobile)->first();
|
||||||
} else {
|
} else {
|
||||||
$user = Customer::where('mobile', $request->mobile)->first();
|
$user = Customer::findActiveByMobile($request->mobile)
|
||||||
|
?? Customer::where('mobile', $request->mobile)->first();
|
||||||
}
|
}
|
||||||
$token = auth($data['provider'])->login($user);
|
$token = auth($data['provider'])->login($user);
|
||||||
$user->last_seen_at = Carbon::now();
|
$user->last_seen_at = Carbon::now();
|
||||||
@@ -33,6 +35,12 @@ class AuthController extends Controller
|
|||||||
return $this->respondWithToken($token);
|
return $this->respondWithToken($token);
|
||||||
}
|
}
|
||||||
$credentials = $request->only(['mobile', 'password']);
|
$credentials = $request->only(['mobile', 'password']);
|
||||||
|
if (($request->provider ?? '') === 'customer') {
|
||||||
|
$normalized = Customer::normalizeMobile($credentials['mobile'] ?? null);
|
||||||
|
if ($normalized !== null) {
|
||||||
|
$credentials['mobile'] = $normalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
return $this->_loginWithPassword($credentials, $request->provider);
|
return $this->_loginWithPassword($credentials, $request->provider);
|
||||||
} else {
|
} else {
|
||||||
return response()->json(
|
return response()->json(
|
||||||
@@ -48,7 +56,8 @@ class AuthController extends Controller
|
|||||||
&& isset($credentials['mobile'], $credentials['password'])
|
&& isset($credentials['mobile'], $credentials['password'])
|
||||||
&& $credentials['password'] === 'montzar@' . $credentials['mobile']
|
&& $credentials['password'] === 'montzar@' . $credentials['mobile']
|
||||||
) {
|
) {
|
||||||
$user = Customer::where('mobile', $credentials['mobile'])->first();
|
$user = Customer::findActiveByMobile($credentials['mobile'])
|
||||||
|
?? Customer::where('mobile', $credentials['mobile'])->first();
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
throw new UnprocessableEntityHttpException('شماره موبایل یا پسوورد وارد شده اشتباه است');
|
throw new UnprocessableEntityHttpException('شماره موبایل یا پسوورد وارد شده اشتباه است');
|
||||||
}
|
}
|
||||||
@@ -65,6 +74,16 @@ class AuthController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$token = auth($provider)->attempt($credentials);
|
$token = auth($provider)->attempt($credentials);
|
||||||
|
if (!$token && $provider === 'customer') {
|
||||||
|
// ردیفهای قدیمی با فرمت موبایل غیرنرمال
|
||||||
|
$fallback = Customer::findActiveByMobile($credentials['mobile'] ?? null);
|
||||||
|
if ($fallback) {
|
||||||
|
$token = auth($provider)->attempt([
|
||||||
|
'mobile' => $fallback->mobile,
|
||||||
|
'password' => $credentials['password'] ?? '',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!$token) {
|
if (!$token) {
|
||||||
throw new UnprocessableEntityHttpException('شماره موبایل یا پسوورد وارد شده اشتباه است');
|
throw new UnprocessableEntityHttpException('شماره موبایل یا پسوورد وارد شده اشتباه است');
|
||||||
}
|
}
|
||||||
@@ -88,7 +107,8 @@ class AuthController extends Controller
|
|||||||
if ($provider == 'user') {
|
if ($provider == 'user') {
|
||||||
$user = User::where('mobile', $mobile)->first();
|
$user = User::where('mobile', $mobile)->first();
|
||||||
} else {
|
} else {
|
||||||
$user = Customer::where('mobile', $mobile)->first();
|
$user = Customer::findActiveByMobile($mobile)
|
||||||
|
?? Customer::where('mobile', $mobile)->first();
|
||||||
}
|
}
|
||||||
if (is_null($user)) {
|
if (is_null($user)) {
|
||||||
throw new UnprocessableEntityHttpException(trans('لطفا ابتدا ثبت نام بفرمایید'));
|
throw new UnprocessableEntityHttpException(trans('لطفا ابتدا ثبت نام بفرمایید'));
|
||||||
@@ -198,9 +218,19 @@ class AuthController extends Controller
|
|||||||
|
|
||||||
$data['active'] = true;
|
$data['active'] = true;
|
||||||
|
|
||||||
Customer::assertMobileUnique($data['mobile'] ?? null);
|
$normalizedMobile = Customer::normalizeMobile($data['mobile'] ?? null);
|
||||||
|
if ($normalizedMobile === null) {
|
||||||
|
throw new UnprocessableEntityHttpException('شماره موبایل نامعتبر است');
|
||||||
|
}
|
||||||
|
$data['mobile'] = $normalizedMobile;
|
||||||
|
|
||||||
$customer = Customer::create($data);
|
$claimable = Customer::findClaimableImportedByMobile($normalizedMobile);
|
||||||
|
if ($claimable && $claimable->isUnclaimedAppIdentity()) {
|
||||||
|
$customer = $this->claimImportedCustomer($claimable, $data);
|
||||||
|
} else {
|
||||||
|
Customer::assertMobileUnique($normalizedMobile);
|
||||||
|
$customer = Customer::create($data);
|
||||||
|
}
|
||||||
|
|
||||||
if ($referrer) {
|
if ($referrer) {
|
||||||
if (Schema::hasColumn((new Customer)->getTable(), 'total_referrals')) {
|
if (Schema::hasColumn((new Customer)->getTable(), 'total_referrals')) {
|
||||||
@@ -241,6 +271,55 @@ class AuthController extends Controller
|
|||||||
$this->Send($data['mobile'], $message);
|
$this->Send($data['mobile'], $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($customer->hasValidPargarAccountId()) {
|
||||||
|
app(PargarInboundWalletService::class)->queueWalletSyncAfterResponse((int) $customer->id);
|
||||||
|
} elseif (! $customer->wasRecentlyCreated) {
|
||||||
|
// claim بدون کد حسابداری — صف export مثل create
|
||||||
|
app(\App\Services\PargarSyncService::class)->registerOnCreate($customer);
|
||||||
|
app(\App\Services\TahesabSyncService::class)->registerOnCreate($customer);
|
||||||
|
}
|
||||||
|
|
||||||
return response()->json($customer);
|
return response()->json($customer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ارتقای ردیف ازقبلواردشده از حسابداری بهجای ساخت مشتری تکراری.
|
||||||
|
*/
|
||||||
|
private function claimImportedCustomer(Customer $customer, array $data): Customer
|
||||||
|
{
|
||||||
|
if (method_exists($customer, 'trashed') && $customer->trashed()) {
|
||||||
|
$customer->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer->fname = $data['fname'] ?? $customer->fname;
|
||||||
|
$customer->lname = $data['lname'] ?? $customer->lname;
|
||||||
|
$customer->name = $data['name'] ?? $customer->name;
|
||||||
|
$customer->mobile = $data['mobile'];
|
||||||
|
$customer->type = $data['type'] ?? $customer->type ?? 2;
|
||||||
|
$customer->active = true;
|
||||||
|
$customer->is_legal = (int) ($data['is_legal'] ?? $customer->is_legal ?? 0);
|
||||||
|
|
||||||
|
if (! empty($data['password'])) {
|
||||||
|
$customer->password = $data['password'];
|
||||||
|
} elseif (empty($customer->password)) {
|
||||||
|
$customer->password = $data['mobile'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! empty($data['n_code'])) {
|
||||||
|
$customer->n_code = $data['n_code'];
|
||||||
|
}
|
||||||
|
if (! empty($data['referral_to_id'])) {
|
||||||
|
$customer->referral_to_id = $data['referral_to_id'];
|
||||||
|
}
|
||||||
|
if (empty($customer->referral_id) && ! empty($data['referral_id'])) {
|
||||||
|
$customer->referral_id = $data['referral_id'];
|
||||||
|
}
|
||||||
|
if (isset($data['gram'])) {
|
||||||
|
$customer->gram = $data['gram'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer->save();
|
||||||
|
|
||||||
|
return $customer->fresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ class PargarInboundController extends Controller
|
|||||||
$customer->pargar_account_id = $accountId;
|
$customer->pargar_account_id = $accountId;
|
||||||
$this->applyPargarCustomerName($customer, $fullName);
|
$this->applyPargarCustomerName($customer, $fullName);
|
||||||
$customer->save();
|
$customer->save();
|
||||||
|
app(PargarInboundWalletService::class)->queueWalletSyncAfterResponse((int) $customer->id);
|
||||||
$messages[] = "کد حسابداری مشتری {$fullName} ویرایش شد";
|
$messages[] = "کد حسابداری مشتری {$fullName} ویرایش شد";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -129,6 +130,7 @@ class PargarInboundController extends Controller
|
|||||||
$byAccount->password = $mobile;
|
$byAccount->password = $mobile;
|
||||||
}
|
}
|
||||||
$byAccount->save();
|
$byAccount->save();
|
||||||
|
app(PargarInboundWalletService::class)->queueWalletSyncAfterResponse((int) $byAccount->id);
|
||||||
$messages[] = "مشتری با کد حسابداری {$accountId} بهروزرسانی شد";
|
$messages[] = "مشتری با کد حسابداری {$accountId} بهروزرسانی شد";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -144,6 +146,7 @@ class PargarInboundController extends Controller
|
|||||||
$customer->referral_id = $this->uniqueReferralId();
|
$customer->referral_id = $this->uniqueReferralId();
|
||||||
$customer->save();
|
$customer->save();
|
||||||
|
|
||||||
|
app(PargarInboundWalletService::class)->queueWalletSyncAfterResponse((int) $customer->id);
|
||||||
$messages[] = "مشتری با کد حسابداری {$accountId} ایجاد شد";
|
$messages[] = "مشتری با کد حسابداری {$accountId} ایجاد شد";
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
$messages[] = "خطا برای {$mobile}: " . (
|
$messages[] = "خطا برای {$mobile}: " . (
|
||||||
@@ -281,19 +284,33 @@ class PargarInboundController extends Controller
|
|||||||
$accountId = trim((string) ($data['AccountId'] ?? ''));
|
$accountId = trim((string) ($data['AccountId'] ?? ''));
|
||||||
|
|
||||||
$customer = Customer::where('pargar_account_id', $accountId)->first();
|
$customer = Customer::where('pargar_account_id', $accountId)->first();
|
||||||
if (! $customer) {
|
|
||||||
return response()->json([
|
|
||||||
'success' => false,
|
|
||||||
'message' => 'مشتری یافت نشد',
|
|
||||||
'data' => null,
|
|
||||||
], 422);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// اگر مشتری هنوز وارد نشده، مانده را با pargar_ref نگه میداریم تا بعد از import/claim اعمال شود
|
||||||
$goldInv = isset($data['GoldInv']) ? (float) str_replace('/', '.', (string) $data['GoldInv']) : 0;
|
$goldInv = isset($data['GoldInv']) ? (float) str_replace('/', '.', (string) $data['GoldInv']) : 0;
|
||||||
$rialInv = isset($data['RialInv']) ? (float) str_replace('/', '.', (string) $data['RialInv']) : 0;
|
$rialInv = isset($data['RialInv']) ? (float) str_replace('/', '.', (string) $data['RialInv']) : 0;
|
||||||
|
|
||||||
// فقط مقایسه برای لاگ — اپ source of truth است؛ کیف را از مانده پرگار عوض نکن
|
if (! $customer) {
|
||||||
// اضطراری: هیچوقت از mande کیف را تغییر نده (حتی اگر کد قدیمی جایی مانده باشد)
|
PargarSyncLog::create([
|
||||||
|
'customer_id' => null,
|
||||||
|
'desc' => 'مانده پرگار — مشتری هنوز در پنل نیست',
|
||||||
|
'type' => PargarSyncService::TYPE_MANDE,
|
||||||
|
'amount' => $goldInv,
|
||||||
|
'sync_status' => PargarSyncService::STATUS_SUCCESS,
|
||||||
|
'pargar_ref' => $accountId,
|
||||||
|
'data' => json_encode(array_merge($data, [
|
||||||
|
'orphan_mande' => true,
|
||||||
|
'wallet_adjusted' => false,
|
||||||
|
]), JSON_UNESCAPED_UNICODE),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'مانده ذخیره شد؛ پس از ثبت مشتری اعمال میشود',
|
||||||
|
'data' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// فقط مقایسه برای لاگ — اعمال روی کیف فقط با دکمه ادمین / صف auto پس از import-claim
|
||||||
$ownerType = (int) ($customer->type ?? 2);
|
$ownerType = (int) ($customer->type ?? 2);
|
||||||
$walletInterface = new WalletInterface($customer->id, $ownerType);
|
$walletInterface = new WalletInterface($customer->id, $ownerType);
|
||||||
$wallet = $walletInterface->wallet;
|
$wallet = $walletInterface->wallet;
|
||||||
@@ -324,6 +341,11 @@ class PargarInboundController extends Controller
|
|||||||
]), JSON_UNESCAPED_UNICODE),
|
]), JSON_UNESCAPED_UNICODE),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// اولین مانده برای مشتریِ هنوز واردنشده به اپ — یکبار همتراز کن
|
||||||
|
if ($customer->last_seen_at === null && $hasDiff) {
|
||||||
|
app(PargarInboundWalletService::class)->queueWalletSyncAfterResponse((int) $customer->id);
|
||||||
|
}
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => 'مانده مشتری با موفقیت دریافت شد',
|
'message' => 'مانده مشتری با موفقیت دریافت شد',
|
||||||
@@ -420,6 +442,8 @@ class PargarInboundController extends Controller
|
|||||||
if ($log) {
|
if ($log) {
|
||||||
$this->sync()->markSuccess($log, $normalizedAccountId);
|
$this->sync()->markSuccess($log, $normalizedAccountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app(PargarInboundWalletService::class)->queueWalletSyncAfterResponse((int) $customer->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+64
-4
@@ -201,13 +201,55 @@ class Customer extends Authenticatable implements JWTSubject
|
|||||||
|
|
||||||
$query = static::query()
|
$query = static::query()
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->where('mobile', $mobile);
|
->whereIn('mobile', self::mobileLookupVariants($mobile));
|
||||||
|
|
||||||
if ($exceptId !== null) {
|
if ($exceptId !== null) {
|
||||||
$query->where('id', '<>', $exceptId);
|
$query->where('id', '<>', $exceptId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query->first();
|
return $query->orderByDesc('id')->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* مشتریِ ازقبلواردشده از حسابداری که هنوز وارد اپ نشده — قابل claim در ثبتنام.
|
||||||
|
* شامل soft-deleted با کد حسابداری (برای جلوگیری از ساخت ردیف تکراری).
|
||||||
|
*/
|
||||||
|
public static function findClaimableImportedByMobile(?string $mobile): ?self
|
||||||
|
{
|
||||||
|
$normalized = self::normalizeMobile($mobile);
|
||||||
|
if ($normalized === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$variants = self::mobileLookupVariants($normalized);
|
||||||
|
|
||||||
|
$active = static::query()
|
||||||
|
->whereNull('deleted_at')
|
||||||
|
->whereIn('mobile', $variants)
|
||||||
|
->whereNull('last_seen_at')
|
||||||
|
->orderByDesc('id')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($active) {
|
||||||
|
return $active;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static::onlyTrashed()
|
||||||
|
->whereIn('mobile', $variants)
|
||||||
|
->whereNull('last_seen_at')
|
||||||
|
->where(function ($q) {
|
||||||
|
$q->where(function ($inner) {
|
||||||
|
$inner->whereNotNull('pargar_account_id')
|
||||||
|
->where('pargar_account_id', '!=', '')
|
||||||
|
->whereNotIn('pargar_account_id', ['0', '-1']);
|
||||||
|
})->orWhere(function ($inner) {
|
||||||
|
$inner->whereNotNull('moshtari_code')
|
||||||
|
->where('moshtari_code', '!=', '')
|
||||||
|
->whereNotIn('moshtari_code', ['0', '-1']);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
->orderByDesc('id')
|
||||||
|
->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isMobileTaken(?string $mobile, ?int $exceptId = null): bool
|
public static function isMobileTaken(?string $mobile, ?int $exceptId = null): bool
|
||||||
@@ -240,14 +282,16 @@ class Customer extends Authenticatable implements JWTSubject
|
|||||||
return $query->exists();
|
return $query->exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function mobileLookupVariants(string $normalized): array
|
public static function mobileLookupVariants(string $normalized): array
|
||||||
{
|
{
|
||||||
$digits = ltrim($normalized, '0');
|
$digits = ltrim($normalized, '0');
|
||||||
|
|
||||||
return array_values(array_unique(array_filter([
|
return array_values(array_unique(array_filter([
|
||||||
$normalized,
|
$normalized,
|
||||||
$digits,
|
$digits,
|
||||||
'0' . $digits,
|
'0'.$digits,
|
||||||
|
'98'.$digits,
|
||||||
|
'+98'.$digits,
|
||||||
])));
|
])));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,4 +319,20 @@ class Customer extends Authenticatable implements JWTSubject
|
|||||||
return self::isValidAccountingCode($this->pargar_account_id);
|
return self::isValidAccountingCode($this->pargar_account_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasValidMoshtariCode(): bool
|
||||||
|
{
|
||||||
|
return self::isValidAccountingCode($this->moshtari_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasAccountingLink(): bool
|
||||||
|
{
|
||||||
|
return $this->hasValidPargarAccountId() || $this->hasValidMoshtariCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** هنوز وارد اپ نشده — معمولاً از import حسابداری آمده */
|
||||||
|
public function isUnclaimedAppIdentity(): bool
|
||||||
|
{
|
||||||
|
return $this->last_seen_at === null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -391,4 +391,48 @@ class PargarInboundWalletService
|
|||||||
|
|
||||||
return (float) str_replace('/', '.', (string) $value);
|
return (float) str_replace('/', '.', (string) $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* پس از اتصال کد پرگار / claim ثبتنام — همگامسازی کیف در پسزمینه.
|
||||||
|
*/
|
||||||
|
public function queueWalletSyncAfterResponse(int $customerId): void
|
||||||
|
{
|
||||||
|
dispatch(function () use ($customerId) {
|
||||||
|
$customer = Customer::find($customerId);
|
||||||
|
if ($customer === null || ! $customer->hasValidPargarAccountId()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->attachOrphanMandeLogs($customer);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->syncWalletFromPargar($customer, true);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::warning('Pargar auto wallet sync failed', [
|
||||||
|
'customer_id' => $customerId,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
})->afterResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* لاگهای ماندهای که قبل از ساخت/لینک مشتری با pargar_ref آمدهاند را به مشتری وصل میکند.
|
||||||
|
*/
|
||||||
|
public function attachOrphanMandeLogs(Customer $customer): int
|
||||||
|
{
|
||||||
|
if (! $customer->hasValidPargarAccountId()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$accountId = trim((string) $customer->pargar_account_id);
|
||||||
|
|
||||||
|
return PargarSyncLog::query()
|
||||||
|
->where('type', PargarSyncService::TYPE_MANDE)
|
||||||
|
->where('pargar_ref', $accountId)
|
||||||
|
->where(function ($q) {
|
||||||
|
$q->whereNull('customer_id')->orWhere('customer_id', 0);
|
||||||
|
})
|
||||||
|
->update(['customer_id' => $customer->id]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ return[
|
|||||||
'provider'=>'required'
|
'provider'=>'required'
|
||||||
],
|
],
|
||||||
'auth/register@post'=>[
|
'auth/register@post'=>[
|
||||||
'mobile' => 'required|digits:11|unique:customers,mobile,NULL,NULL,deleted_at,NULL',
|
// یکتایی موبایل در AuthController با منطق claim مشتریِ ازقبلواردشده از حسابداری چک میشود
|
||||||
|
'mobile' => 'required|digits:11',
|
||||||
'fname'=>'required',
|
'fname'=>'required',
|
||||||
'lname'=>'required',
|
'lname'=>'required',
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user