fix pargar bug
This commit is contained in:
@@ -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', '');
|
||||
|
||||
Reference in New Issue
Block a user