feat(tahesab,colleague): push app balance to Tahesab and always wait callback

Add admin decision to write app wallet onto Tahesab even when zero, always await colleague callback regardless of the wait switch, and SMS admins on colleague reject.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-05 22:30:56 +03:30
co-authored by Cursor
parent 8cee34bfba
commit 00b23ac404
6 changed files with 176 additions and 15 deletions
@@ -16,9 +16,8 @@ class ColleagueOrderCallbackService
public function waitEnabled(): bool
{
$config = app(ConfigService::class);
return $config->usesMontzarPricing() && $config->getBool('montzar_order_wait_callback', true);
// همیشه منتظر کالبک/استعلام همکار — سوییچ montzar_order_wait_callback دیگر مسیر «قطعی بلافاصله» را باز نمی‌کند
return app(ConfigService::class)->usesMontzarPricing();
}
public function callbackUrl(int $localOrderId): string
+1 -2
View File
@@ -627,8 +627,7 @@ class MontzarService
];
if (
$this->config()->getBool('montzar_order_wait_callback', true)
&& isset($data['order'])
isset($data['order'])
&& $data['order'] instanceof Order
) {
$payload['callback'] = app(ColleagueOrderCallbackService::class)->callbackUrl((int) $data['order']->id);
+112 -4
View File
@@ -19,10 +19,11 @@ use Rooyesh\Wallet\models\Wallet;
* MandeyeKolBePool → موجودی ریالی
*
* سیاست تصمیم ادمین:
* overwrite=true → اختلاف را اعمال کن
* keep=true → موجودی اپ را دست نزن
* ask_if_conflict → اگر اپ مانده دارد و با ته‌حساب فرق دارد، بدون نوشتن برگردان
* always_ask → هر اختلافی (حتی کیف خالی) بدون نوشتن برای تأیید ادمین برمی‌گردد
* overwrite=true → اختلاف را روی کیف اپ اعمال کن (ته‌حساب → اپ)
* keep=true → موجودی اپ را دست نزن
* push_to_tahesab → مانده اپ را با سند تعدیل روی ته‌حساب بنویس (حتی اگر اپ صفر باشد)
* ask_if_conflict → اگر اپ مانده دارد و با ته‌حساب فرق دارد، بدون نوشتن برگردان
* always_ask → هر اختلافی (حتی کیف خالی) بدون نوشتن برای تأیید ادمین برمی‌گردد
* جمع دو مانده هرگز انجام نمی‌شود تا موجودی دو برابر نشود.
*/
class TahesabInboundWalletService
@@ -190,6 +191,113 @@ class TahesabInboundWalletService
]);
}
/**
* ماندهٔ اپ → ته‌حساب (سند تعدیل در ته‌حساب؛ کیف اپ دست نخورده).
* حتی اگر اپ صفر باشد، مانده ته‌حساب با سند برداشت/واریز هم‌تراز اپ می‌شود.
*
* @param array{gold?: float, cash?: float}|null $mande
* @return array{
* applied: bool,
* gold_delta?: float,
* rial_delta?: float,
* app_gold?: float,
* app_cash?: float,
* tahesab_gold?: float,
* tahesab_cash?: float,
* message: string
* }
*/
public function pushWalletToTahesab(Customer $customer, ?array $mande = null): array
{
$code = (int) ($customer->moshtari_code ?? 0);
if ($code <= 0) {
return ['applied' => false, 'message' => 'کد ته‌حساب ندارد'];
}
if ($mande === null) {
$all = $this->fetchMandeByCodes([$code]);
$mande = $all[(string) $code] ?? null;
}
if ($mande === null) {
return ['applied' => false, 'message' => 'مانده از ته‌حساب دریافت نشد'];
}
$compared = $this->compareWithWallet($customer, $mande);
$comparison = $compared['comparison'];
$goldSame = $compared['gold_same'];
$rialSame = $compared['rial_same'];
if ($goldSame && $rialSame) {
return array_merge($comparison, [
'applied' => false,
'message' => 'مانده با ته‌حساب یکسان است',
]);
}
$controller = app(\App\Http\Controllers\Admin\TahesabController::class);
$note = 'تعدیل مانده از اپ به ته‌حساب';
$errors = [];
// gold_delta در مقایسه = ته‌حساب − اپ؛ برای رساندن ته‌حساب به اپ باید معکوس اعمال شود
if (! $goldSame) {
$goldToAdd = (float) $comparison['app_gold'] - (float) $comparison['tahesab_gold'];
$goldOk = $controller->walletGold([
'customer_id' => (int) $customer->id,
'value' => abs($goldToAdd),
'direction' => $goldToAdd > 0 ? 1 : 0,
'note' => $note,
]);
if ($goldOk === false || is_string($goldOk)) {
$errors[] = is_string($goldOk) && $goldOk !== ''
? $goldOk
: 'ثبت سند طلایی تعدیل در ته‌حساب ناموفق بود';
}
}
if (! $rialSame) {
$cashToAdd = (float) $comparison['app_cash'] - (float) $comparison['tahesab_cash'];
$cashOk = $controller->wallet([
'customer_id' => (int) $customer->id,
'value' => (int) round(abs($cashToAdd)),
'direction' => $cashToAdd > 0 ? 0 : 1,
'note' => $note,
]);
if ($cashOk === false || is_string($cashOk)) {
$errors[] = is_string($cashOk) && $cashOk !== ''
? $cashOk
: 'ثبت سند ریالی تعدیل در ته‌حساب ناموفق بود';
}
}
if ($errors !== []) {
Log::warning('Tahesab push wallet from app failed', [
'customer_id' => (int) $customer->id,
'moshtari_code' => $code,
'errors' => $errors,
]);
return array_merge($comparison, [
'applied' => false,
'message' => implode('؛ ', $errors),
]);
}
Log::info('Tahesab wallet pushed from app', [
'customer_id' => (int) $customer->id,
'moshtari_code' => $code,
'app_gold' => $comparison['app_gold'],
'app_cash' => $comparison['app_cash'],
'tahesab_gold_before' => $comparison['tahesab_gold'],
'tahesab_cash_before' => $comparison['tahesab_cash'],
]);
return array_merge($comparison, [
'applied' => true,
'message' => 'مانده اپ روی ته‌حساب اعمال شد (کیف اپ تغییر نکرد)',
]);
}
/**
* مقایسه بدون نوشتن — برای تأیید ادمین قبل از ست کردن کد.
*