fix pargar bug

This commit is contained in:
2026-07-20 15:52:42 +03:30
parent 160d6bd923
commit a809a843b8
7 changed files with 586 additions and 62 deletions
@@ -25,6 +25,7 @@ use App\Models\TransactionsAdmin;
use App\Services\AssetSummaryService;
use App\Services\BalanceReportService;
use App\Services\ConfigService;
use App\Services\PargarSyncService;
use App\Services\WalletBalanceService;
use App\Services\WalletBroadcastService;
use Hekmatinasser\Verta\Verta;
@@ -83,6 +84,20 @@ class WalletController extends Controller
'active' => true
], 3, false, true, $gold_block);
try {
app(PargarSyncService::class)->queueWalletDocument(
$customer,
'cash',
(float) $data['value'],
[
'withdraw_id' => $Withdraw->id,
'source' => 'admin_charge2',
]
);
} catch (\Throwable $e) {
report($e);
}
$message = 'کیف پول شما به مبلغ ' . self::formatSmsRialAmount($data['value']) . " ریال در تاریخ " . verta()->format('Y/n/j H:i:s') . " شارژ شد " . "\n"
. $this->Config('name_fa');
$this->Send($customer->mobile, $message);
@@ -140,6 +155,21 @@ class WalletController extends Controller
}
}
try {
app(PargarSyncService::class)->queueWalletDocument(
$customer,
'cash',
(float) $data['value'],
[
'withdraw_id' => $Withdraw->id,
'note' => $data['note'] ?? null,
'source' => 'admin_cash',
]
);
} catch (\Throwable $e) {
report($e);
}
//send sms to users and customer
$status = $data['value'] > 0 ?" شارژ شد ": " کسر شد ";
if (self::isSmsNotifEnabled('charge_notif')) {
@@ -212,6 +242,23 @@ class WalletController extends Controller
report($e);
}
}
try {
app(PargarSyncService::class)->queueWalletDocument(
$customer,
'gold',
(float) $data['value'],
[
'withdraw_id' => $Withdraw->id,
'note' => $data['note'] ?? null,
'product_id' => $representative?->id,
'source' => 'admin_gold',
]
);
} catch (\Throwable $e) {
report($e);
}
//send sms to users and customer
$status = $data['value'] > 0 ?" شارژ شد ": " کسر شد ";
$weightUnit = self::tradeWeightUnit();
@@ -361,6 +408,23 @@ class WalletController extends Controller
}
}
try {
// فقط محصول متصل به کیف اصلی → سند طلای پرگار
app(PargarSyncService::class)->queueWalletDocument(
$customer,
'gold',
(float) $data['value'],
[
'withdraw_id' => $Withdraw->id,
'note' => $data['note'] ?? null,
'product_id' => $productId,
'source' => 'admin_product',
]
);
} catch (\Throwable $e) {
report($e);
}
$status = $deposit ? ' شارژ شد ' : ' کسر شد ';
$formatted = self::formatSmsGoldWeight($data['value']);
@@ -386,7 +386,10 @@ class CartController extends Controller
if ($config->isPargarAccounting()) {
try {
app(PargarSyncService::class)->recordTrade($order, true);
app(PargarSyncService::class)->recordTrade($order, true, [
'payment_kind' => PargarSyncService::PAYMENT_CASH,
'product_id' => null,
]);
} catch (\Throwable $e) {
report($e);
}
@@ -8,13 +8,11 @@ use App\Models\Cart;
use App\Models\Customer;
use App\Models\Order;
use App\Models\PargarSyncLog;
use App\Models\Product;
use App\Services\ConfigService;
use App\Services\PargarSyncService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Schema;
use Morilog\Jalali\Jalalian;
use Rooyesh\Wallet\interfaces\TransactionInterface;
use Rooyesh\Wallet\interfaces\WalletInterface;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
@@ -164,44 +162,41 @@ class PargarInboundController extends Controller
public function listOrders(Request $request)
{
$documents = collect();
$orders = Order::query()
->where('sts', 2)
->whereNull('pargar_confirmed_at')
->limit(100)
->get();
$documents = $orders->map(function (Order $order) {
$customer = Customer::find((int) ($order->customer_id ?? 0));
foreach ($orders as $order) {
$payload = $this->orderExportPayload($order);
if ($payload === null) {
continue;
}
$documents->push($payload);
}
// direction اپ: 1=خرید مشتری، 2=فروش مشتری
// OrderType پرگار از دید فروشگاه است: خرید مشتری = فروش فروشگاه (-1)، فروش مشتری = خرید فروشگاه (1)
$isCustomerBuy = (int) ($order->direction ?? 1) === 1;
$customerDirection = (int) ($order->direction ?? 0);
$walletLogs = PargarSyncLog::query()
->whereIn('type', [PargarSyncService::TYPE_WALLET_CASH, PargarSyncService::TYPE_WALLET_GOLD])
->where('sync_status', PargarSyncService::STATUS_PENDING)
->orderBy('id')
->limit(100)
->get();
return [
'OrderId' => (string) $order->id,
'OrderType' => $isCustomerBuy ? -1 : 1,
'PriceType' => 1,
'CustomerAccountId' => (int) ($customer->pargar_account_id ?? 0),
'ItemId' => 11,
'ItemName' => $this->pargarItemName($order),
'OrderDate' => $order->pay_at
? Jalalian::fromDateTime($order->pay_at)->format('Y/m/d-H:i:s')
: Jalalian::fromDateTime($order->created_at)->format('Y/m/d-H:i:s'),
'Fee' => (float) ($order->price ?? 0),
'Count' => 1,
'Weight' => (float) ($order->amount ?? 0),
'Price' => (float) ($order->total_price ?? 0),
'Carat' => 750,
'Description' => self::accountingShopTradeDesc($customerDirection, $this->isCartOrder($order)),
];
})->values();
foreach ($walletLogs as $log) {
$payload = $this->walletExportPayload($log);
if ($payload !== null) {
$documents->push($payload);
}
}
return response()->json([
'state' => 'true',
'msg' => '',
'data' => [
'documents' => $documents,
'documents' => $documents->values(),
'duplicated' => 'false',
'result' => 'OK',
],
@@ -242,7 +237,7 @@ class PargarInboundController extends Controller
PargarSyncLog::create([
'customer_id' => $customer?->id,
'desc' => 'دریافت اسناد از پرگار',
'type' => 'document',
'type' => PargarSyncService::TYPE_DOCUMENT,
'sync_status' => PargarSyncService::STATUS_SUCCESS,
'pargar_ref' => $accountId,
'data' => json_encode($data, JSON_UNESCAPED_UNICODE),
@@ -272,33 +267,35 @@ class PargarInboundController extends Controller
$goldInv = isset($data['GoldInv']) ? (float) str_replace('/', '.', (string) $data['GoldInv']) : 0;
$rialInv = isset($data['RialInv']) ? (float) str_replace('/', '.', (string) $data['RialInv']) : 0;
// خواندن و نوشتن روی همان کیف اصلی مشتری — نه first() تصادفی
// فقط مقایسه برای لاگ — اپ source of truth است؛ کیف را از مانده پرگار عوض نکن
$ownerType = (int) ($customer->type ?? 2);
$walletInterface = new WalletInterface($customer->id, $ownerType);
$wallet = $walletInterface->wallet;
$goldDiff = $goldInv - (float) ($wallet->gold ?? 0);
$rialDiff = $rialInv - (float) ($wallet->cash ?? 0);
$appGold = (float) ($wallet->gold ?? 0);
$appCash = (float) ($wallet->cash ?? 0);
$goldDiff = $goldInv - $appGold;
$rialDiff = $rialInv - $appCash;
$hasDiff = abs($goldDiff) >= 0.01 || abs($rialDiff) >= 1;
if (abs($goldDiff) >= 0.01 || abs($rialDiff) >= 1) {
new TransactionInterface($walletInterface, [
'cash' => $rialDiff,
'gold' => $goldDiff,
'title' => 'تعدیل حسابداری پرگار',
'expire_at' => now(),
'active' => true,
'start_at' => now(),
], 22, $goldDiff > 0, $rialDiff > 0);
}
$desc = $hasDiff
? 'اختلاف مانده پرگار با اپ — کیف اپ دست نخورده'
: 'دریافت مانده از پرگار — بدون اختلاف';
PargarSyncLog::create([
'customer_id' => $customer->id,
'desc' => 'دریافت مانده از پرگار',
'type' => 'mande',
'desc' => $desc,
'type' => PargarSyncService::TYPE_MANDE,
'amount' => $goldInv,
'sync_status' => PargarSyncService::STATUS_SUCCESS,
'pargar_ref' => $accountId,
'data' => json_encode($data, JSON_UNESCAPED_UNICODE),
'data' => json_encode(array_merge($data, [
'app_gold' => $appGold,
'app_cash' => $appCash,
'gold_diff' => $goldDiff,
'rial_diff' => $rialDiff,
'wallet_adjusted' => false,
]), JSON_UNESCAPED_UNICODE),
]);
return response()->json([
@@ -495,4 +492,162 @@ class PargarInboundController extends Controller
->whereIn('desc', ['سبد خرید', 'فروش سبد به مشتری'])
->exists();
}
/**
* @return array<string, mixed>|null
*/
private function orderExportPayload(Order $order): ?array
{
$sync = $this->sync();
$log = PargarSyncLog::where('order_id', $order->id)->latest('id')->first();
$payload = $log ? (json_decode((string) $log->data, true) ?: []) : [];
$paymentKind = (string) ($payload['payment_kind'] ?? PargarSyncService::PAYMENT_CASH);
if ($paymentKind === PargarSyncService::PAYMENT_OTHER_PRODUCT) {
return null;
}
if ($log && is_string($log->pargar_ref) && str_starts_with($log->pargar_ref, 'skip:')) {
return null;
}
$customer = Customer::find((int) ($order->customer_id ?? 0));
$isCustomerBuy = (int) ($order->direction ?? 1) === 1;
$customerDirection = (int) ($order->direction ?? 0);
$fromCart = (bool) ($payload['from_cart'] ?? $this->isCartOrder($order));
$product = $sync->resolveOrderProduct($order, $payload);
$number = (float) ($payload['number'] ?? 0);
$amount = (float) ($order->amount ?? 0);
$totalPrice = (float) ($order->total_price ?? $order->payment_amount ?? 0);
$unitPrice = (float) ($order->price ?? 0);
$isCountBased = $product
? self::isCountBasedProduct(self::productUnitPayload($product))
: false;
$count = 1;
$weight = $amount;
if ($isCountBased && $number > 0) {
$count = max(1, (int) round($number));
$weight = $amount;
} elseif ($number > 0 && abs($number - $amount) > 0.0001) {
$count = max(1, (int) round($number));
}
$itemId = $sync->pargarItemIdGold();
$itemName = $this->pargarItemName($order);
if ($product && trim((string) $product->title) !== '') {
$itemName = trim((string) $product->title);
}
$tradedProductId = (int) ($payload['product_id'] ?? $order->product_id ?? 0);
$tradesMainGold = $tradedProductId <= 0
|| app(ConfigService::class)->isMainWalletProduct($tradedProductId);
// اثر مانده از روش پرداخت؛ وزن طلا فقط وقتی کالای معامله یا پرداخت به کیف اصلی مربوط است
if ($paymentKind === PargarSyncService::PAYMENT_CASH) {
if ($tradesMainGold) {
// خرید/فروش آبشده کیف‌اصلی با نقدی: وزن + مبلغ
$itemId = $sync->pargarItemIdGold();
} else {
// محصول غیر اصلی با پرداخت نقدی: فقط ریال
$rialItemId = $sync->pargarItemIdRial();
$itemId = $rialItemId > 0 ? $rialItemId : $sync->pargarItemIdGold();
$weight = 0;
$count = 1;
}
} elseif ($paymentKind === PargarSyncService::PAYMENT_MAIN_GOLD) {
$itemId = $sync->pargarItemIdGold();
$itemName = $sync->mainWalletGoldItemName();
$paymentGold = (float) ($payload['payment_gold'] ?? $amount);
$weight = abs($paymentGold);
$totalPrice = 0;
}
return [
'OrderId' => (string) $order->id,
'OrderType' => $isCustomerBuy ? -1 : 1,
'PriceType' => 1,
'CustomerAccountId' => (int) ($customer->pargar_account_id ?? 0),
'ItemId' => $itemId,
'ItemName' => $itemName,
'OrderDate' => $order->pay_at
? Jalalian::fromDateTime($order->pay_at)->format('Y/m/d-H:i:s')
: Jalalian::fromDateTime($order->created_at)->format('Y/m/d-H:i:s'),
'Fee' => $unitPrice,
'Count' => $count,
'Weight' => $weight,
'Price' => $totalPrice,
'Carat' => 750,
'Description' => self::accountingShopTradeDesc($customerDirection, $fromCart),
];
}
/**
* @return array<string, mixed>|null
*/
private function walletExportPayload(PargarSyncLog $log): ?array
{
$sync = $this->sync();
$payload = json_decode((string) $log->data, true) ?: [];
$kind = (string) ($payload['kind'] ?? ($log->type === PargarSyncService::TYPE_WALLET_GOLD ? 'gold' : 'cash'));
$signed = (float) ($payload['signed_amount'] ?? $log->amount ?? 0);
if (abs($signed) < ($kind === 'cash' ? 1 : 0.01)) {
$signed = (float) ($log->amount ?? 0);
// اگر علامت نبود، از desc حدس بزن — پیش‌فرض واریز مثبت
if (! isset($payload['signed_amount']) && is_string($log->desc) && str_contains($log->desc, 'برداشت')) {
$signed = -abs($signed);
} elseif (! isset($payload['signed_amount'])) {
$signed = abs($signed);
}
}
$customer = Customer::find((int) ($log->customer_id ?? 0));
$withdrawId = (int) ($log->withdraw_id ?? 0);
$orderId = $withdrawId > 0 ? 'W-' . $withdrawId : 'WLOG-' . $log->id;
$isDeposit = $signed >= 0;
// OrderType از دید فروشگاه: واریز به مشتری = فروشگاه بدهکار؟ قرارداد قبلی خرید مشتری = -1
// واریز ریالی مشتری ≈ افزایش بدهی فروشگاه به مشتری از نظر حساب → مشابه خرید نیست؛
// برای واریز: OrderType=1 (ورود وجه به حساب مشتری در پرگار بسته به نرم‌افزار)
// هم‌راستا با آذین: اسناد کیف را با OrderType بر اساس علامت می‌فرستیم
$orderType = $isDeposit ? 1 : -1;
if ($kind === 'gold') {
return [
'OrderId' => $orderId,
'OrderType' => $orderType,
'PriceType' => 1,
'CustomerAccountId' => (int) ($customer->pargar_account_id ?? 0),
'ItemId' => $sync->pargarItemIdGold(),
'ItemName' => $sync->mainWalletGoldItemName(),
'OrderDate' => Jalalian::fromDateTime($log->date ?? $log->created_at)->format('Y/m/d-H:i:s'),
'Fee' => 0,
'Count' => 1,
'Weight' => abs($signed),
'Price' => 0,
'Carat' => 750,
'Description' => $isDeposit ? 'شارژ طلای کیف اصلی' : 'برداشت طلای کیف اصلی',
];
}
$rialItemId = $sync->pargarItemIdRial();
return [
'OrderId' => $orderId,
'OrderType' => $orderType,
'PriceType' => 1,
'CustomerAccountId' => (int) ($customer->pargar_account_id ?? 0),
'ItemId' => $rialItemId > 0 ? $rialItemId : $sync->pargarItemIdGold(),
'ItemName' => $isDeposit ? 'واریز ریالی' : 'برداشت ریالی',
'OrderDate' => Jalalian::fromDateTime($log->date ?? $log->created_at)->format('Y/m/d-H:i:s'),
'Fee' => 0,
'Count' => 1,
'Weight' => 0,
'Price' => abs($signed),
'Carat' => 750,
'Description' => $isDeposit ? 'واریز ریالی' : 'برداشت ریالی',
];
}
}
@@ -208,7 +208,30 @@ class SingleOrderController extends Controller
if ($config->isPargarAccounting()) {
try {
app(\App\Services\PargarSyncService::class)->recordTrade($data['order'] ?? null);
$paymentProductId = (int) ($data['payment_product_id'] ?? 0);
$paymentKind = app(\App\Services\PargarSyncService::class)
->inferPaymentKindFromContext([
'payment_product_id' => $paymentProductId,
]);
// خرید/فروش عادی از کیف ریالی (بدون payment_product_id) = نقدی
if ($paymentProductId <= 0) {
$paymentKind = \App\Services\PargarSyncService::PAYMENT_CASH;
}
$paymentGold = null;
if ($paymentKind === \App\Services\PargarSyncService::PAYMENT_MAIN_GOLD) {
$paymentGold = (float) ($data['total_amount'] ?? $data['amount'] ?? 0);
}
app(\App\Services\PargarSyncService::class)->recordTrade(
$data['order'] ?? null,
false,
[
'payment_kind' => $paymentKind,
'payment_product_id' => $paymentProductId > 0 ? $paymentProductId : null,
'product_id' => (int) ($data['product_id'] ?? 0) ?: null,
'number' => isset($data['number']) ? (float) $data['number'] : null,
'payment_gold' => $paymentGold,
]
);
} catch (\Throwable $e) {
report($e);
}
@@ -182,6 +182,21 @@ class paypingController extends Controller
'active' => true,
], 3, false, true);
try {
app(\App\Services\PargarSyncService::class)->queueWalletDocument(
$User,
'cash',
(float) ($GTransaction['amount'] * 10),
[
'withdraw_id' => $Withdraw->id,
'note' => 'واریز درگاه',
'source' => 'gateway',
]
);
} catch (\Throwable $e) {
report($e);
}
$message = 'کاربر ' . $Withdraw->customer->name . ' با شماره موبایل ' . $Withdraw->customer->mobile
. ' حساب خود را به مقدار ' . number_format($Withdraw->cash) . ' ریال شارژ کرد. با تشکر، ' . $this->Config('name_fa');
@@ -238,6 +253,21 @@ class paypingController extends Controller
'active' => true,
], 3, false, true);
try {
app(\App\Services\PargarSyncService::class)->queueWalletDocument(
$User,
'cash',
(float) ($decodedResponse['data']['amount'] * 10),
[
'withdraw_id' => (int) $Withdraw->id,
'note' => 'واریز درگاه',
'source' => 'gateway',
]
);
} catch (\Throwable $e) {
report($e);
}
if ($this->cfg()->getBool('payping_fin_sync_enabled', (bool) config('payment.payping_fin_sync_enabled', false))) {
$finUrl = $this->cfg()->getString('payping_fin_url', 'https://limangold.ir/kernel/admin/fin');
$finToken = $this->cfg()->getString('payping_fin_token', '');
+248 -13
View File
@@ -5,6 +5,7 @@ namespace App\Services;
use App\Models\Customer;
use App\Models\Order;
use App\Models\PargarSyncLog;
use App\Models\Product;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
@@ -14,6 +15,17 @@ class PargarSyncService
public const STATUS_SUCCESS = 'success';
public const STATUS_FAILED = 'failed';
public const TYPE_CUSTOMER = 'customer';
public const TYPE_ORDER = 'order';
public const TYPE_MANDE = 'mande';
public const TYPE_DOCUMENT = 'document';
public const TYPE_WALLET_CASH = 'wallet_cash';
public const TYPE_WALLET_GOLD = 'wallet_gold';
public const PAYMENT_CASH = 'cash';
public const PAYMENT_MAIN_GOLD = 'main_gold';
public const PAYMENT_OTHER_PRODUCT = 'other_product';
public function buildLog(mixed $response = null, ?string $extra = null): string
{
$parts = array_filter([
@@ -93,7 +105,7 @@ class PargarSyncService
{
$existing = PargarSyncLog::query()
->where('customer_id', $customer->id)
->where('type', 'customer')
->where('type', self::TYPE_CUSTOMER)
->where('sync_status', self::STATUS_PENDING)
->latest('id')
->first();
@@ -105,7 +117,7 @@ class PargarSyncService
return PargarSyncLog::create([
'customer_id' => $customer->id,
'desc' => 'در انتظار دریافت توسط پرگار',
'type' => 'customer',
'type' => self::TYPE_CUSTOMER,
'sync_status' => self::STATUS_PENDING,
'data' => json_encode(['handler' => 'exportCustomer'], JSON_UNESCAPED_UNICODE),
]);
@@ -132,7 +144,84 @@ class PargarSyncService
];
}
public function recordTrade(?Order $order, bool $fromCart = false): ?PargarSyncLog
/**
* صف سند کیف برای سینک مانده پرگار با اپ.
*
* @param 'cash'|'gold' $kind
* @param array{withdraw_id?:int|null,note?:string|null,product_id?:int|null,source?:string|null} $meta
*/
public function queueWalletDocument(
Customer $customer,
string $kind,
float $signedAmount,
array $meta = []
): ?PargarSyncLog {
if (! $this->isSyncEnabled() || ! $this->hasSyncTable()) {
return null;
}
if (abs($signedAmount) < ($kind === 'cash' ? 1 : 0.01)) {
return null;
}
if ($kind === 'gold') {
$productId = (int) ($meta['product_id'] ?? 0);
if ($productId > 0 && ! app(ConfigService::class)->isMainWalletProduct($productId)) {
return null;
}
} elseif ($kind !== 'cash') {
return null;
}
$withdrawId = isset($meta['withdraw_id']) ? (int) $meta['withdraw_id'] : null;
$type = $kind === 'cash' ? self::TYPE_WALLET_CASH : self::TYPE_WALLET_GOLD;
if ($withdrawId) {
$existing = PargarSyncLog::query()
->where('withdraw_id', $withdrawId)
->where('type', $type)
->latest('id')
->first();
if ($existing) {
return $existing;
}
}
$isDeposit = $signedAmount > 0;
if ($kind === 'cash') {
$desc = $isDeposit ? 'واریز ریالی — ارسال به پرگار' : 'برداشت ریالی — ارسال به پرگار';
} else {
$desc = $isDeposit ? 'شارژ طلای کیف اصلی — ارسال به پرگار' : 'برداشت طلای کیف اصلی — ارسال به پرگار';
}
return PargarSyncLog::create([
'customer_id' => $customer->id,
'amount' => abs($signedAmount),
'desc' => $desc,
'withdraw_id' => $withdrawId,
'date' => now(),
'type' => $type,
'sync_status' => self::STATUS_PENDING,
'data' => json_encode([
'handler' => 'exportWallet',
'kind' => $kind,
'signed_amount' => $signedAmount,
'note' => $meta['note'] ?? null,
'product_id' => $meta['product_id'] ?? null,
'source' => $meta['source'] ?? null,
], JSON_UNESCAPED_UNICODE),
]);
}
/**
* @param array{
* payment_kind?: string,
* payment_product_id?: int|null,
* product_id?: int|null,
* number?: float|null
* } $context
*/
public function recordTrade(?Order $order, bool $fromCart = false, array $context = []): ?PargarSyncLog
{
if (! $order || ! $order->id || ! $this->isSyncEnabled()) {
return null;
@@ -146,29 +235,123 @@ class PargarSyncService
$direction = (int) ($order->direction ?? 0);
$desc = \App\Http\Controllers\Controller::accountingShopTradeDesc($direction, $fromCart);
$paymentKind = $context['payment_kind']
?? $this->inferPaymentKindFromContext($context);
$payload = [
'handler' => 'exportOrder',
'direction' => $direction,
'price' => $order->price,
'total_price' => $order->total_price,
'payment_kind' => $paymentKind,
'payment_product_id' => $context['payment_product_id'] ?? null,
'product_id' => $context['product_id'] ?? $order->product_id ?? null,
'number' => $context['number'] ?? null,
'payment_gold' => $context['payment_gold'] ?? null,
'from_cart' => $fromCart,
];
// تهاتر بین دو محصول غیر اصلی — روی ریال/طلای پرگار اثر ندارد
if ($paymentKind === self::PAYMENT_OTHER_PRODUCT) {
$order->pargar_confirmed_at = now();
$order->save();
return PargarSyncLog::create([
'customer_id' => $order->customer_id,
'amount' => $order->amount,
'desc' => $desc . ' (تهاتر محصول — بدون سند ریال/طلای پرگار)',
'order_id' => $order->id,
'date' => $order->pay_at ?? $order->created_at,
'type' => self::TYPE_ORDER,
'sync_status' => self::STATUS_SUCCESS,
'pargar_ref' => 'skip:barter',
'data' => json_encode($payload, JSON_UNESCAPED_UNICODE),
]);
}
return PargarSyncLog::create([
'customer_id' => $order->customer_id,
'amount' => $order->amount,
'desc' => $desc,
'order_id' => $order->id,
'date' => $order->pay_at ?? $order->created_at,
'type' => 'order',
'type' => self::TYPE_ORDER,
'sync_status' => self::STATUS_PENDING,
'data' => json_encode([
'handler' => 'exportOrder',
'direction' => $direction,
'price' => $order->price,
'total_price' => $order->total_price,
], JSON_UNESCAPED_UNICODE),
'data' => json_encode($payload, JSON_UNESCAPED_UNICODE),
]);
}
/**
* @param array{payment_kind?: string, payment_product_id?: int|null} $context
*/
public function inferPaymentKindFromContext(array $context): string
{
if (! empty($context['payment_kind'])) {
return (string) $context['payment_kind'];
}
$paymentProductId = (int) ($context['payment_product_id'] ?? 0);
if ($paymentProductId <= 0) {
return self::PAYMENT_CASH;
}
return app(ConfigService::class)->isMainWalletProduct($paymentProductId)
? self::PAYMENT_MAIN_GOLD
: self::PAYMENT_OTHER_PRODUCT;
}
public function confirmOrders(array $orderIds): array
{
$confirmed = 0;
foreach ($orderIds as $orderId) {
$order = Order::find($orderId);
$id = trim((string) $orderId);
if ($id === '') {
continue;
}
if (str_starts_with(strtoupper($id), 'W-')) {
$withdrawId = (int) substr($id, 2);
if ($withdrawId <= 0) {
continue;
}
$log = PargarSyncLog::query()
->where('withdraw_id', $withdrawId)
->whereIn('type', [self::TYPE_WALLET_CASH, self::TYPE_WALLET_GOLD])
->where('sync_status', self::STATUS_PENDING)
->latest('id')
->first();
if ($log) {
$this->markSuccess($log, $id, ['OrderId' => $id]);
$confirmed++;
}
continue;
}
if (str_starts_with(strtoupper($id), 'WLOG-')) {
$logId = (int) substr($id, 5);
if ($logId <= 0) {
continue;
}
$log = PargarSyncLog::query()
->where('id', $logId)
->whereIn('type', [self::TYPE_WALLET_CASH, self::TYPE_WALLET_GOLD])
->where('sync_status', self::STATUS_PENDING)
->first();
if ($log) {
$this->markSuccess($log, $id, ['OrderId' => $id]);
$confirmed++;
}
continue;
}
$order = Order::find($id);
if (! $order) {
continue;
}
@@ -227,6 +410,21 @@ class PargarSyncService
];
}
if ($handler === 'exportWallet') {
PargarSyncLog::where('id', $log->id)->update([
'sync_status' => self::STATUS_PENDING,
'sync_log' => null,
'pargar_ref' => null,
]);
$log->refresh();
return [
'ok' => true,
'message' => 'سند کیف دوباره در صف ارسال به پرگار قرار گرفت',
'pargar' => $log,
];
}
return [
'ok' => false,
'message' => $log->sync_log ?: 'ارسال مجدد به پرگار ناموفق بود',
@@ -240,11 +438,15 @@ class PargarSyncService
return 'exportOrder';
}
if ($log->type === 'customer') {
if ($log->type === self::TYPE_CUSTOMER) {
return 'exportCustomer';
}
if ($log->type === 'mande') {
if (in_array($log->type, [self::TYPE_WALLET_CASH, self::TYPE_WALLET_GOLD], true)) {
return 'exportWallet';
}
if ($log->type === self::TYPE_MANDE) {
return 'importMande';
}
@@ -264,4 +466,37 @@ class PargarSyncService
{
return Schema::hasTable('pargar_sync_logs');
}
public function pargarItemIdRial(): int
{
$raw = trim(app(ConfigService::class)->getString('pargar_item_id_rial', '0'));
return max(0, (int) $raw);
}
public function pargarItemIdGold(): int
{
$raw = trim(app(ConfigService::class)->getString('pargar_item_id_gold', '11'));
$id = (int) $raw;
return $id > 0 ? $id : 11;
}
public function mainWalletGoldItemName(): string
{
$product = app(ConfigService::class)->mainWalletRepresentativeProduct();
$title = trim((string) ($product?->title ?? ''));
return $title !== '' ? $title : 'آبشده';
}
public function resolveOrderProduct(?Order $order, ?array $payload = null): ?Product
{
$productId = (int) ($payload['product_id'] ?? $order?->product_id ?? 0);
if ($productId <= 0) {
return null;
}
return Product::find($productId);
}
}