feat(payments): expose primary transfer candidate
This commit is contained in:
@@ -4,6 +4,7 @@ namespace App\Domains\Purchase\Resources;
|
||||
|
||||
use App\Domains\Purchase\Models\Purchase;
|
||||
use App\Domains\Purchase\Models\PurchaseItem;
|
||||
use App\Domains\Purchase\Models\TelepagosPaymentCandidate;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
@@ -23,6 +24,7 @@ class PurchaseResource extends JsonResource
|
||||
$ticketsCount = array_key_exists('tickets_count', $this->resource->getAttributes())
|
||||
? (int) $this->resource->getAttribute('tickets_count')
|
||||
: null;
|
||||
$paymentVerification = $this->resolvePaymentVerification();
|
||||
|
||||
$subtotal = $items->isNotEmpty()
|
||||
? $items->reduce(
|
||||
@@ -58,6 +60,7 @@ class PurchaseResource extends JsonResource
|
||||
'items' => PurchaseItemResource::collection($items),
|
||||
'tickets_count' => $this->when($ticketsCount !== null, $ticketsCount),
|
||||
'has_generated_tickets' => $this->when($ticketsCount !== null, $ticketsCount > 0),
|
||||
'payment_verification' => $this->when($paymentVerification !== null, $paymentVerification),
|
||||
'subtotal' => $this->formatMoney($subtotal),
|
||||
'total' => $this->formatMoney($total),
|
||||
];
|
||||
@@ -77,4 +80,74 @@ class PurchaseResource extends JsonResource
|
||||
{
|
||||
return number_format((float) ($amount ?? 0), 2, '.', '');
|
||||
}
|
||||
|
||||
/** @return array<string, mixed>|null */
|
||||
private function resolvePaymentVerification(): ?array
|
||||
{
|
||||
if (
|
||||
$this->status !== Purchase::STATUS_IN_REVIEW
|
||||
|| $this->payment_method !== 'transfer'
|
||||
|| ! $this->resource->relationLoaded('telepagosPaymentCandidates')
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$candidates = $this->resource
|
||||
->getRelation('telepagosPaymentCandidates')
|
||||
->sort(fn (TelepagosPaymentCandidate $left, TelepagosPaymentCandidate $right): int => $this->comparePaymentCandidates($left, $right))
|
||||
->values();
|
||||
/** @var TelepagosPaymentCandidate|null $primary */
|
||||
$primary = $candidates->first();
|
||||
|
||||
return [
|
||||
'status' => $primary === null ? 'pending' : 'candidate',
|
||||
'candidate_count' => $candidates->count(),
|
||||
'primary' => $primary === null ? null : [
|
||||
'reason' => $primary->match_reason,
|
||||
'payment_amount' => $this->formatMoney($primary->payment_amount),
|
||||
'purchase_amount' => $this->formatMoney($primary->purchase_amount),
|
||||
'amount_difference' => $this->formatMoney($primary->amount_difference),
|
||||
'confidence' => $primary->confidence,
|
||||
'detected_at' => $primary->payment?->created_at?->toIso8601String(),
|
||||
],
|
||||
'reasons' => $candidates
|
||||
->pluck('match_reason')
|
||||
->unique()
|
||||
->values()
|
||||
->all(),
|
||||
];
|
||||
}
|
||||
|
||||
private function comparePaymentCandidates(
|
||||
TelepagosPaymentCandidate $left,
|
||||
TelepagosPaymentCandidate $right,
|
||||
): int {
|
||||
$reasonComparison = $this->paymentCandidateRank($left->match_reason)
|
||||
<=> $this->paymentCandidateRank($right->match_reason);
|
||||
|
||||
if ($reasonComparison !== 0) {
|
||||
return $reasonComparison;
|
||||
}
|
||||
|
||||
$differenceComparison = (float) $left->amount_difference <=> (float) $right->amount_difference;
|
||||
|
||||
if ($differenceComparison !== 0) {
|
||||
return $differenceComparison;
|
||||
}
|
||||
|
||||
$leftTimestamp = $left->payment?->created_at?->getTimestamp() ?? 0;
|
||||
$rightTimestamp = $right->payment?->created_at?->getTimestamp() ?? 0;
|
||||
|
||||
return ($rightTimestamp <=> $leftTimestamp) ?: ($right->id <=> $left->id);
|
||||
}
|
||||
|
||||
private function paymentCandidateRank(string $reason): int
|
||||
{
|
||||
return match ($reason) {
|
||||
'ambiguous_exact_match' => 0,
|
||||
'exact_dni_near_amount' => 1,
|
||||
'exact_amount_different_dni' => 2,
|
||||
default => 3,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user