added some feature for accounting

This commit is contained in:
2026-08-30 20:47:26 +03:30
parent 283f17561c
commit c27cfabd22
3 changed files with 128 additions and 0 deletions
@@ -874,6 +874,55 @@ class TahesabController extends Controller
]); ]);
} }
/**
* لیست مشتریان لینک‌شده با مقایسهٔ کیف و ماندهٔ ته‌حساب.
*/
public function walletLinkedList(Request $request): \Illuminate\Http\JsonResponse
{
if (! app(ConfigService::class)->isTahesabAccounting()) {
return response()->json([
'ok' => false,
'message' => 'حسابداری ته‌حساب فعال نیست',
], 422);
}
$search = trim((string) $request->input('search', ''));
$page = max(1, (int) $request->input('page', 1));
$perPage = max(1, min(50, (int) $request->input('per_page', 20)));
$base = Customer::query()
->whereNull('deleted_at')
->whereNotNull('moshtari_code')
->where('moshtari_code', '!=', '')
->where('moshtari_code', '!=', '0');
if ($search !== '') {
$base->where(function ($q) use ($search) {
$q->where('name', 'like', '%'.$search.'%')
->orWhere('mobile', 'like', '%'.$search.'%')
->orWhere('moshtari_code', 'like', '%'.$search.'%');
});
}
$total = (clone $base)->count();
$customers = (clone $base)
->orderBy('id')
->offset(($page - 1) * $perPage)
->limit($perPage)
->get(['id', 'name', 'mobile', 'moshtari_code', 'type']);
$rows = app(TahesabInboundWalletService::class)->compareCustomers($customers);
return response()->json([
'ok' => true,
'total' => $total,
'page' => $page,
'per_page' => $perPage,
'last_page' => max(1, (int) ceil($total / max(1, $perPage))),
'rows' => $rows,
]);
}
private function tahesabApiUrl(): string private function tahesabApiUrl(): string
{ {
$host = trim((string) $this->Config('tahesab_host')); $host = trim((string) $this->Config('tahesab_host'));
@@ -234,6 +234,84 @@ class TahesabInboundWalletService
return $this->parseMandeRow($row); return $this->parseMandeRow($row);
} }
/**
* مقایسهٔ کیف اپ با ماندهٔ ته‌حساب برای لیست ادمین — بدون نوشتن.
*
* @param iterable<Customer> $customers
* @return list<array<string, mixed>>
*/
public function compareCustomers(iterable $customers): array
{
$list = [];
foreach ($customers as $customer) {
if ($customer instanceof Customer) {
$list[] = $customer;
}
}
if ($list === []) {
return [];
}
$codes = [];
foreach ($list as $customer) {
$code = (int) ($customer->moshtari_code ?? 0);
if ($code > 0) {
$codes[] = $code;
}
}
$mandes = $this->fetchMandeByCodes($codes);
$rows = [];
foreach ($list as $customer) {
$code = (int) ($customer->moshtari_code ?? 0);
$mande = $code > 0 ? ($mandes[(string) $code] ?? null) : null;
$base = [
'id' => (int) $customer->id,
'name' => (string) ($customer->name ?? ''),
'mobile' => (string) ($customer->mobile ?? ''),
'moshtari_code' => $code > 0 ? $code : null,
];
if ($mande === null) {
$ownerType = (int) ($customer->type ?? 2);
$wallet = (new WalletInterface((int) $customer->id, $ownerType))->wallet;
$appGold = $this->walletBalance
->accountingVisibleMainWalletGold((int) $customer->id, $ownerType);
$appCash = (float) ($wallet->cash ?? 0);
$rows[] = array_merge($base, [
'app_gold' => $appGold,
'app_cash' => $appCash,
'tahesab_gold' => null,
'tahesab_cash' => null,
'gold_delta' => null,
'rial_delta' => null,
'status' => 'missing',
'message' => 'مانده از ته‌حساب دریافت نشد',
]);
continue;
}
$compared = $this->compareWithWallet($customer, $mande);
$same = $compared['gold_same'] && $compared['rial_same'];
$status = 'conflict';
if ($same) {
$status = 'same';
} elseif (! $compared['app_has_balance']) {
$status = 'ready';
}
$rows[] = array_merge($base, $compared['comparison'], [
'status' => $status,
'message' => $same
? 'مانده با ته‌حساب یکسان است'
: ($status === 'ready'
? 'کیف خالی است؛ همگام‌سازی مانده ته‌حساب را می‌نشاند'
: 'موجودی اپ با ته‌حساب فرق دارد'),
]);
}
return $rows;
}
/** /**
* @param array{gold?: float, cash?: float} $mande * @param array{gold?: float, cash?: float} $mande
* @return array{ * @return array{
+1
View File
@@ -254,6 +254,7 @@ Route::middleware('auth:user')->group(function (){
Route::post('tahesab/customer-sync/rollback-import', [TahesabController::class, 'rollbackImport']); Route::post('tahesab/customer-sync/rollback-import', [TahesabController::class, 'rollbackImport']);
Route::post('tahesab/mande-by-codes', [TahesabController::class, 'mandeByCodes']); Route::post('tahesab/mande-by-codes', [TahesabController::class, 'mandeByCodes']);
Route::post('tahesab/wallet-sync/all', [TahesabController::class, 'syncAllWallets']); Route::post('tahesab/wallet-sync/all', [TahesabController::class, 'syncAllWallets']);
Route::get('tahesab/wallet-sync/list', [TahesabController::class, 'walletLinkedList']);
Route::get('tahesab/{id}', [TahesabController::class, 'show']); Route::get('tahesab/{id}', [TahesabController::class, 'show']);
Route::post('tahesab/{id}/retry', [TahesabController::class, 'retrySanad']); Route::post('tahesab/{id}/retry', [TahesabController::class, 'retrySanad']);
Route::post('customer/{id}/tahesab/register', [TahesabController::class, 'registerCustomer']); Route::post('customer/{id}/tahesab/register', [TahesabController::class, 'registerCustomer']);