fix(odeme): önce kredi sonra paid damgası; çift pakette iade akışı; UNIQUE tespiti
All checks were successful
Deploy / deploy (push) Successful in 8m50s
All checks were successful
Deploy / deploy (push) Successful in 8m50s
- odemeyiSonuclandir krediyi yazıp sonra paid damgalar; araya kesinti girerse
sipariş pending kalır ve yeniden denenir (eskiden: paid görünür, kredi yok).
paid + deftersiz eski siparişler ilk ziyarette onarılır
- paket tek seferlik: grantCredits({ paketTekil }) zaten paketliye yazmaz
(kontrol UPDATE'in WHERE'inde). Sipariş paid damgalanır, senkron log +
destek@ e-postası, /odeme/sonuc 'Bu ödeme iade edilecek' kartı, /kosullar#iade
- drizzle DrizzleQueryError üst mesajında 'UNIQUE' yok → idempotent no-op yerine
hata fırlıyordu (grant + iki spend yolu); cause zincirine bakılıyor
- callback geçici DB hatasında 500 yerine sonuç sayfasına yönlendirir
- krediKaydiVarMi (reason, ref_id) indeksini kullanır; haftalık mutabakat sorgusu
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import Link from "next/link";
|
||||
import { ArrowRight, CheckCircle2, XCircle } from "lucide-react";
|
||||
import { ArrowRight, CheckCircle2, RotateCcw, XCircle } from "lucide-react";
|
||||
import { verifySession } from "@/lib/session";
|
||||
import { siparisGetir } from "../odeme-queries";
|
||||
import { kullanicininRaporu } from "@/features/rapor/rapor-queries";
|
||||
import { odemeyiSonuclandir } from "@/lib/odeme";
|
||||
import { iadeEdilecekMi, odemeyiSonuclandir } from "@/lib/odeme";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { PagePixelDivider } from "@/components/pixel-decor";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
@@ -23,16 +23,54 @@ export async function OdemeSonucKarti({ siparis }: { siparis?: string }) {
|
||||
// Yalnızca kendi siparişi görüntülenebilir
|
||||
const sahibiMi = order?.userId === session.user.id;
|
||||
|
||||
// Self-healing: callback kaybolduysa burada tekrar doğrula
|
||||
// Self-healing: callback kaybolduysa burada tekrar doğrula. "paid" siparişte
|
||||
// de çağrılır — kredisi yazılmamış eski kayıtları onarır (idempotent).
|
||||
const durum =
|
||||
order && sahibiMi
|
||||
? order.status === "paid"
|
||||
? "paid"
|
||||
: await odemeyiSonuclandir(order.id)
|
||||
: "not_found";
|
||||
order && sahibiMi ? await odemeyiSonuclandir(order.id) : "not_found";
|
||||
|
||||
const basarili = durum === "paid";
|
||||
|
||||
// Zaten paketliyken alınan ikinci paket ödemesi: kredi yazılmadı, iade edilir
|
||||
const iade =
|
||||
basarili && order
|
||||
? await iadeEdilecekMi({ ...order, status: "paid" })
|
||||
: false;
|
||||
if (iade) {
|
||||
return (
|
||||
<div className="rounded-2xl border border-amber-200 bg-white p-8 shadow-sm">
|
||||
<RotateCcw className="mx-auto size-12 text-amber-500" aria-hidden />
|
||||
<h1 className="mt-4 font-heading text-2xl font-bold">
|
||||
Bu ödeme iade edilecek
|
||||
</h1>
|
||||
<p className="mt-2 text-sm text-slate-600">
|
||||
Tercih Dönemi Paketi'n zaten aktifti; paket tek seferlik olduğu
|
||||
için bu ikinci ödemeyi iade ediyoruz — senin bir şey yapmana gerek
|
||||
yok. İade en geç 14 gün içinde yapılır; kartına yansıması bankana
|
||||
göre birkaç gün daha sürebilir. Sorun olursa{" "}
|
||||
<a
|
||||
href="mailto:destek@kolaytercih.com"
|
||||
className="font-medium text-primary underline-offset-2 hover:underline"
|
||||
>
|
||||
destek@kolaytercih.com
|
||||
</a>
|
||||
'a yaz.
|
||||
</p>
|
||||
<PagePixelDivider seed={79} className="mx-auto mt-5" />
|
||||
<div className="mt-6 flex flex-col gap-2">
|
||||
<Button
|
||||
asChild
|
||||
className="h-11 cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600"
|
||||
>
|
||||
<Link href="/listem">
|
||||
Listeme dön
|
||||
<ArrowRight className="size-4" aria-hidden />
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Rapor zaten üretildiyse ödül bir tık uzakta: kullanıcıyı doğrudan
|
||||
// rapor sayfasına döndür ki blur çözülme animasyonuyla tam listeyi görsün.
|
||||
const rapor = basarili ? await kullanicininRaporu(session.user.id) : null;
|
||||
|
||||
Reference in New Issue
Block a user