<?php
namespace App\Jobs;
use App\Models\{LedgerAccount,LedgerEntry,MerchantBalanceSnapshot};use Illuminate\Bus\Queueable;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Foundation\Bus\Dispatchable;use Illuminate\Queue\InteractsWithQueue;use Illuminate\Queue\SerializesModels;use Illuminate\Support\Facades\DB;
final class MerchantBalanceStatementSnapshotJob implements ShouldQueue {use Dispatchable,InteractsWithQueue,Queueable,SerializesModels;public function __construct(){$this->onQueue('reconciliation');}public function handle():void{$accounts=LedgerAccount::whereNotNull('merchant_id')->get()->groupBy(fn($a)=>"{$a->merchant_id}:{$a->asset_id}");foreach($accounts as $group){$first=$group->first();$values=[];foreach(['merchant_pending'=>'pending_atomic','merchant_available'=>'available_atomic','merchant_reserved'=>'reserved_atomic'] as $type=>$field){$a=$group->firstWhere('type',$type);$values[$field]=$a?(string)LedgerEntry::where('account_id',$a->id)->selectRaw("COALESCE(SUM(CASE WHEN direction='credit' THEN amount_atomic ELSE -amount_atomic END),0) as balance")->value('balance'):'0';}MerchantBalanceSnapshot::updateOrCreate(['merchant_id'=>$first->merchant_id,'asset_id'=>$first->asset_id,'environment'=>config('gateway.environment'),'statement_date'=>today()],$values);}}}
