added some feature for accounting and enhance performance for dashboard

This commit is contained in:
2026-08-30 20:18:48 +03:30
parent e059a4709e
commit 283f17561c
6 changed files with 1251 additions and 84 deletions
+109 -33
View File
@@ -19,6 +19,8 @@ use Rooyesh\Wallet\interfaces\WalletInterface;
* overwrite=true → اختلاف را اعمال کن
* keep=true → موجودی اپ را دست نزن
* ask_if_conflict → اگر اپ مانده دارد و با ته‌حساب فرق دارد، بدون نوشتن برگردان
* always_ask → هر اختلافی (حتی کیف خالی) بدون نوشتن برای تأیید ادمین برمی‌گردد
* جمع دو مانده هرگز انجام نمی‌شود تا موجودی دو برابر نشود.
*/
class TahesabInboundWalletService
{
@@ -67,7 +69,7 @@ class TahesabInboundWalletService
/**
* @param array{gold?: float, cash?: float}|null $mande
* @param array{overwrite?: bool, keep?: bool, ask_if_conflict?: bool} $options
* @param array{overwrite?: bool, keep?: bool, ask_if_conflict?: bool, always_ask?: bool} $options
* @return array{
* applied: bool,
* needs_decision?: bool,
@@ -86,6 +88,7 @@ class TahesabInboundWalletService
$overwrite = (bool) ($options['overwrite'] ?? false);
$keep = (bool) ($options['keep'] ?? false);
$askIfConflict = (bool) ($options['ask_if_conflict'] ?? false);
$alwaysAsk = (bool) ($options['always_ask'] ?? false);
$code = (int) ($customer->moshtari_code ?? 0);
if ($code <= 0) {
@@ -101,31 +104,11 @@ class TahesabInboundWalletService
return ['applied' => false, 'message' => 'مانده از ته‌حساب دریافت نشد'];
}
$goldInv = (float) ($mande['gold'] ?? 0);
$rialInv = (float) ($mande['cash'] ?? 0);
$ownerType = (int) ($customer->type ?? 2);
$walletInterface = new WalletInterface((int) $customer->id, $ownerType);
$wallet = $walletInterface->wallet;
$mainGold = $this->walletBalance
->accountingVisibleMainWalletGold((int) $customer->id, $ownerType);
$mainCash = (float) ($wallet->cash ?? 0);
$goldDiff = $goldInv - $mainGold;
$rialDiff = $rialInv - $mainCash;
$goldSame = abs($goldDiff) < self::EPSILON_GOLD;
$rialSame = abs($rialDiff) < self::EPSILON_CASH;
$comparison = [
'app_gold' => $mainGold,
'app_cash' => $mainCash,
'tahesab_gold' => $goldInv,
'tahesab_cash' => $rialInv,
'gold_delta' => $goldDiff,
'rial_delta' => $rialDiff,
];
$compared = $this->compareWithWallet($customer, $mande);
$comparison = $compared['comparison'];
$goldSame = $compared['gold_same'];
$rialSame = $compared['rial_same'];
$appHasBalance = $compared['app_has_balance'];
if ($goldSame && $rialSame) {
return array_merge($comparison, [
@@ -142,11 +125,11 @@ class TahesabInboundWalletService
]);
}
$appHasBalance = abs($mainGold) >= self::EPSILON_GOLD
|| abs($mainCash) >= self::EPSILON_CASH;
// اگر اپ مانده دارد و با ته‌حساب فرق دارد و ادمین هنوز تصمیم نگرفته
if ($askIfConflict && ! $overwrite && $appHasBalance) {
$needsAsk = ! $overwrite && (
($alwaysAsk)
|| ($askIfConflict && $appHasBalance)
);
if ($needsAsk) {
return array_merge($comparison, [
'applied' => false,
'needs_decision' => true,
@@ -154,6 +137,11 @@ class TahesabInboundWalletService
]);
}
$goldDiff = (float) $comparison['gold_delta'];
$rialDiff = (float) $comparison['rial_delta'];
$ownerType = (int) ($customer->type ?? 2);
$walletInterface = new WalletInterface((int) $customer->id, $ownerType);
$input = [
'title' => 'تطبیق ماندهٔ ته‌حساب',
'note' => 'tahesab-mande:'.$code,
@@ -186,8 +174,8 @@ class TahesabInboundWalletService
Log::info('Tahesab mande applied to wallet', [
'customer_id' => (int) $customer->id,
'moshtari_code' => $code,
'gold_target' => $goldInv,
'cash_target' => $rialInv,
'gold_target' => $comparison['tahesab_gold'],
'cash_target' => $comparison['tahesab_cash'],
'gold_delta' => $goldDiff,
'rial_delta' => $rialDiff,
'overwrite' => $overwrite,
@@ -199,6 +187,94 @@ class TahesabInboundWalletService
]);
}
/**
* مقایسه بدون نوشتن — برای تأیید ادمین قبل از ست کردن کد.
*
* @return array{
* applied: bool,
* needs_decision?: bool,
* ok?: bool,
* app_gold?: float,
* app_cash?: float,
* tahesab_gold?: float,
* tahesab_cash?: float,
* gold_delta?: float,
* rial_delta?: float,
* message: string
* }
*/
public function previewForCustomer(Customer $customer, int $code): array
{
if ($code <= 0) {
return ['applied' => false, 'ok' => false, 'message' => 'کد ته‌حساب نامعتبر است'];
}
$all = $this->fetchMandeByCodes([$code]);
$mande = $all[(string) $code] ?? null;
if ($mande === null) {
return ['applied' => false, 'ok' => false, 'message' => 'مانده از ته‌حساب دریافت نشد'];
}
$compared = $this->compareWithWallet($customer, $mande);
$same = $compared['gold_same'] && $compared['rial_same'];
return array_merge($compared['comparison'], [
'applied' => false,
'ok' => true,
'needs_decision' => ! $same,
'message' => $same
? 'مانده با ته‌حساب یکسان است'
: 'موجودی اپ با ته‌حساب فرق دارد — تصمیم ادمین لازم است',
]);
}
/** @param array<string, mixed> $row */
public function mandeFromAccountingRow(array $row): ?array
{
return $this->parseMandeRow($row);
}
/**
* @param array{gold?: float, cash?: float} $mande
* @return array{
* comparison: array{app_gold: float, app_cash: float, tahesab_gold: float, tahesab_cash: float, gold_delta: float, rial_delta: float},
* gold_same: bool,
* rial_same: bool,
* app_has_balance: bool
* }
*/
private function compareWithWallet(Customer $customer, array $mande): array
{
$goldInv = (float) ($mande['gold'] ?? 0);
$rialInv = (float) ($mande['cash'] ?? 0);
$ownerType = (int) ($customer->type ?? 2);
$walletInterface = new WalletInterface((int) $customer->id, $ownerType);
$wallet = $walletInterface->wallet;
$mainGold = $this->walletBalance
->accountingVisibleMainWalletGold((int) $customer->id, $ownerType);
$mainCash = (float) ($wallet->cash ?? 0);
$goldDiff = $goldInv - $mainGold;
$rialDiff = $rialInv - $mainCash;
return [
'comparison' => [
'app_gold' => $mainGold,
'app_cash' => $mainCash,
'tahesab_gold' => $goldInv,
'tahesab_cash' => $rialInv,
'gold_delta' => $goldDiff,
'rial_delta' => $rialDiff,
],
'gold_same' => abs($goldDiff) < self::EPSILON_GOLD,
'rial_same' => abs($rialDiff) < self::EPSILON_CASH,
'app_has_balance' => abs($mainGold) >= self::EPSILON_GOLD
|| abs($mainCash) >= self::EPSILON_CASH,
];
}
/**
* بعد از import: اگر کیف خالی باشد مانده را بنشان؛ اگر مانده دارد صبر کن تا ادمین تصمیم بگیرد.
*