where('tenant_codigo', $tenant->codigo) ->where('user_id', $request->user()->id) ->when($request->query('status'), function ($query, $status) { $query->where('status', $status); }) ->latest() ->paginateFromRequest() )->response(); } public function startCheckout( StartCheckoutRequest $request, Tenant $tenant, CheckoutService $checkoutService, ): JsonResponse { $data = $request->validated(); $purchase = $checkoutService->startCheckout( $tenant, $request->user()->id, $data ); return PurchaseResource::make($purchase)->response()->setStatusCode(201); } public function show(Request $request, Tenant $tenant, Purchase $compra): PurchaseResource { $compra = $this->resolveScopedPurchase($tenant, $request->user()->id, $compra); $compra->loadMissing('items')->loadCount('tickets'); $compra->items->load('imageAttachment'); return PurchaseResource::make($compra); } public function updateCustomerData( UpdatePurchaseCustomerRequest $request, Tenant $tenant, Purchase $compra, CheckoutService $checkoutService, ): PurchaseResource { $compra = $this->resolveScopedPurchase($tenant, $request->user()->id, $compra); return PurchaseResource::make( $checkoutService->updateCustomerData($compra, $request->validated()), ); } public function updateItemQuantity( UpdatePurchaseItemQuantityRequest $request, Tenant $tenant, Purchase $compra, PurchaseItem $item, CheckoutService $checkoutService, ): PurchaseResource { $compra = $this->resolveScopedPurchase($tenant, $request->user()->id, $compra); return PurchaseResource::make( $checkoutService->updateItemQuantity( $compra, $item, (int) $request->validated('quantity'), ), ); } public function prepareItemEditing( Request $request, Tenant $tenant, Purchase $compra, CheckoutService $checkoutService, ): PurchaseResource { $compra = $this->resolveScopedPurchase($tenant, $request->user()->id, $compra); return PurchaseResource::make( $checkoutService->prepareItemEditing($compra), ); } public function paymentIntent(PaymentIntentRequest $request, Tenant $tenant, Purchase $compra): JsonResponse { $compra = $this->resolveScopedPurchase($tenant, $request->user()->id, $compra); $method = $request->validated('method'); $totalAmount = $compra->calculateCurrentTotalAmount(); $purchaseUpdate = [ 'payment_method' => $method, 'status' => Purchase::STATUS_PENDING_PAYMENT, 'expires_at' => now()->addMinutes( max(1, (int) config("purchase.payment_expiration_minutes.{$method}", 30)) ), 'total' => $totalAmount, ]; if ($method === 'transfer') { $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); if ($updated === 0) { throw ValidationException::withMessages([ 'purchase' => __('api.purchase.not_available_for_payment'), ]); } $compra->refresh(); if ($method === 'transfer') { $telepagosService = new TelepagosIntegrationService; $telepagosService->forTenant($tenant->codigo); try { $accountInfo = $telepagosService->getAccountInfo(); return response()->json([ 'payment_method' => 'transfer', 'transfer_data' => [ 'titular' => $accountInfo['holder'] ?? null, 'cvu' => $accountInfo['cvu'] ?? null, 'alias' => $accountInfo['alias'] ?? null, 'cuit' => $accountInfo['cuit'] ?? null, 'entidad' => $accountInfo['entity'] ?? 'Telepagos S.A.', ], ]); } catch (\Exception $e) { Log::error('Unable to retrieve TelePagos account information.', [ 'purchase_id' => $compra->id, 'exception' => $e, ]); return response()->json([ 'code' => 'integration.account_info_failed', 'message' => __('api.integration.account_info_failed'), ], 500); } } if ($method === 'qr') { $telepagosService = new TelepagosIntegrationService; $telepagosService->forTenant($tenant->codigo); try { Log::info("Generating QR for purchase ID: {$compra->id}, amount: {$totalAmount}"); $qrResponse = $telepagosService->generateQr( $totalAmount, 'Compra', "Compra #{$compra->id}" ); $telepagosQr = $compra->telepagosQr()->create([ 'qr_order_id' => (string) ($qrResponse['qr_order_id'] ?? ''), 'qr_code' => $qrResponse['qr_code'] ?? '', ]); } catch (\Exception $e) { Log::error('Unable to generate TelePagos QR code.', [ 'purchase_id' => $compra->id, 'exception' => $e, ]); return response()->json([ 'code' => 'integration.qr_generation_failed', 'message' => __('api.integration.qr_generation_failed'), ], 500); } return response()->json([ 'payment_method' => 'qr', 'qr_data' => [ 'qr_code' => $telepagosQr->qr_code, 'qr_order_id' => $telepagosQr->qr_order_id, ], ]); } return response()->json([ 'code' => 'integration.invalid_payment_method', 'message' => __('api.integration.invalid_payment_method'), ], 400); } public function complete(Request $request, Tenant $tenant, Purchase $compra, CheckoutService $checkoutService): PurchaseResource { $compra = $this->resolveScopedPurchase($tenant, $request->user()->id, $compra); return PurchaseResource::make( $checkoutService->completePurchase($compra) ); } public function submitForReview( Request $request, Tenant $tenant, Purchase $compra, CheckoutService $checkoutService, ): PurchaseResource { $compra = $this->resolveScopedPurchase($tenant, $request->user()->id, $compra); return PurchaseResource::make( $checkoutService->submitForReview($compra), ); } public function cancel(Request $request, Tenant $tenant, Purchase $compra, CheckoutService $checkoutService): PurchaseResource { $compra = $this->resolveScopedPurchase($tenant, $request->user()->id, $compra); return PurchaseResource::make( $checkoutService->cancelPurchase($compra) ); } protected function resolveScopedPurchase(Tenant $tenant, int $userId, Purchase $purchase): Purchase { if ($purchase->tenant_codigo !== $tenant->codigo || $purchase->user_id !== $userId) { throw new NotFoundHttpException(__('api.errors.not_found')); } return $purchase; } }