findOrFail($this->settlementId); $lines = SettlementLine::withoutGlobalScopes()->where('settlement_id', $settlement->id)->get(); foreach ($lines as $line) { $order = null; $status = 'ignored'; $matchedAmount = '0'; if (! empty($line->external_order_id)) { $order = Order::withoutGlobalScopes() ->where('store_id', $settlement->store_id) ->where('external_order_id', $line->external_order_id) ->first(); if (! $order) { $status = 'unmatched'; } else { $matchedAmount = $line->amount; $status = $this->amountMatches($line->amount, $this->expectedAmount($order, $line->line_type)) ? 'auto_matched' : 'partial_matched'; } } ReconciliationMatch::withoutGlobalScopes()->updateOrCreate( ['settlement_line_id' => $line->id, 'order_id' => $order?->id], [ 'company_id' => $settlement->company_id, 'match_type' => $status === 'auto_matched' ? 'rule' : 'exception', 'matched_amount' => $matchedAmount, 'status' => $status, 'rule_version' => '1.0', ] ); } } private function expectedAmount(Order $order, string $lineType): string { if ($lineType === 'refund') { return $order->refunded_amount; } return bcsub( bcadd($order->buyer_paid_amount, $order->platform_subsidy_amount, 6), $order->refunded_amount, 6 ); } private function amountMatches(string $actual, string $expected): bool { return bccomp(ltrim($actual, '-'), ltrim($expected, '-'), 6) === 0; } }