feat: Remove 'in_review' status from purchase workflow; implement logging for status changes and update related tests

This commit is contained in:
2026-08-03 17:04:39 -03:00
parent c4b317d5fc
commit 96f26e2e9d
8 changed files with 92 additions and 27 deletions

View File

@@ -57,13 +57,9 @@ class TelepagosWebhookService
->whereIn('status', [
Purchase::STATUS_CREATED,
Purchase::STATUS_PENDING_PAYMENT,
Purchase::STATUS_IN_REVIEW,
])
->where('payment_method', 'transfer')
->where('total', $amount)
->orderByRaw('CASE WHEN status = ? THEN 0 ELSE 1 END', [
Purchase::STATUS_IN_REVIEW,
])
->latest()
->first();
@@ -97,7 +93,6 @@ class TelepagosWebhookService
if (! in_array($compra->status, [
Purchase::STATUS_PENDING_PAYMENT,
Purchase::STATUS_IN_REVIEW,
], true)) {
Log::warning("Telepagos webhook: Purchase {$compra->id} is not awaiting payment confirmation");

View File

@@ -15,6 +15,7 @@ use App\Domains\Tenant\Models\Tenant;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -124,14 +125,28 @@ class PurchaseController extends Controller
$purchaseUpdate['transfer_payer_dni'] = preg_replace('/\D+/', '', (string) $request->validated('transfer_payer_dni'));
}
$updated = Purchase::query()
->whereKey($compra->getKey())
->whereIn('status', [Purchase::STATUS_CREATED, Purchase::STATUS_PENDING_PAYMENT])
->where(function ($query): void {
$query->whereNull('expires_at')
->orWhere('expires_at', '>', now());
})
->update($purchaseUpdate);
$updated = DB::transaction(function () use ($compra, $purchaseUpdate): bool {
/** @var Purchase|null $purchase */
$purchase = Purchase::query()
->whereKey($compra->getKey())
->lockForUpdate()
->first();
if (
$purchase === null
|| ! in_array($purchase->status, [
Purchase::STATUS_CREATED,
Purchase::STATUS_PENDING_PAYMENT,
], true)
|| ($purchase->expires_at !== null && $purchase->expires_at->isPast())
) {
return false;
}
$purchase->update($purchaseUpdate);
return true;
});
if ($updated === 0) {
throw ValidationException::withMessages([

View File

@@ -4,6 +4,7 @@ namespace App\Domains\Purchase\Models;
use App\Domains\Auth\Models\User;
use App\Domains\Cart\Models\Cart;
use App\Domains\Logging\Models\Concerns\LogsValueChanges;
use App\Domains\Purchase\Events\PurchasePaid;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Ticket\Models\Ticket;
@@ -31,14 +32,12 @@ use Illuminate\Support\Facades\DB;
])]
class Purchase extends Model
{
use HasFactory;
use HasFactory, LogsValueChanges;
public const STATUS_CREATED = 'created';
public const STATUS_PENDING_PAYMENT = 'pending_payment';
public const STATUS_IN_REVIEW = 'in_review';
public const STATUS_PAID = 'paid';
public const STATUS_CANCELLED = 'cancelled';
@@ -49,6 +48,11 @@ class Purchase extends Model
protected $table = 'compras';
/** @var array<int, string> */
protected array $loggedAttributes = [
'status',
];
protected function casts(): array
{
return [

View File

@@ -70,7 +70,6 @@ class CheckoutService
if (in_array($purchase->status, [
Purchase::STATUS_PAID,
Purchase::STATUS_IN_REVIEW,
Purchase::STATUS_CANCELLED,
Purchase::STATUS_REJECTED,
Purchase::STATUS_EXPIRED,
@@ -96,7 +95,6 @@ class CheckoutService
->findOrFail($purchase->getKey());
if (in_array($purchase->status, [
Purchase::STATUS_IN_REVIEW,
Purchase::STATUS_PAID,
], true)) {
return $this->loadPurchase($purchase);
@@ -112,7 +110,6 @@ class CheckoutService
}
$purchase->update([
'status' => Purchase::STATUS_IN_REVIEW,
'expires_at' => null,
]);