Compare commits
2 Commits
9bd448bd16
...
43b6ceca3e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43b6ceca3e | ||
|
|
4acfd27ab1 |
@@ -164,7 +164,12 @@ export async function ListemIcerik({
|
|||||||
kilitAcilisi={kilitAcilisi}
|
kilitAcilisi={kilitAcilisi}
|
||||||
kilitliBaslangic={user.hasPaket ? undefined : ACIK_SATIR}
|
kilitliBaslangic={user.hasPaket ? undefined : ACIK_SATIR}
|
||||||
kredi={user.creditBalance}
|
kredi={user.creditBalance}
|
||||||
raporKredi={RAPOR_KREDI}
|
raporKredi={
|
||||||
|
/* Liste ve revizyon pakete dâhil (bkz. rapor-actions.ts'teki
|
||||||
|
maliyet): paketliye bedel 0 iner ki arayüz sunucunun yaptığını
|
||||||
|
söylesin. */
|
||||||
|
user.hasPaket ? 0 : RAPOR_KREDI
|
||||||
|
}
|
||||||
sohbetGecmisi={sohbetGecmisi as Mesaj[]}
|
sohbetGecmisi={sohbetGecmisi as Mesaj[]}
|
||||||
ozet={danismanOzeti}
|
ozet={danismanOzeti}
|
||||||
ilkYorum={ilkYorum}
|
ilkYorum={ilkYorum}
|
||||||
|
|||||||
@@ -6,10 +6,12 @@
|
|||||||
// alanların değiştiğini gösterir ve listeyi yeni tercihlere göre yeniden
|
// alanların değiştiğini gösterir ve listeyi yeni tercihlere göre yeniden
|
||||||
// kurmayı önerir.
|
// kurmayı önerir.
|
||||||
//
|
//
|
||||||
// Yeniden kurulum normal üretimle AYNI kapıdan geçer (listeOlustur): 3 kredi,
|
// Yeniden kurulum normal üretimle AYNI kapıdan geçer (listeOlustur): aynı
|
||||||
// aynı requestId idempotency'si, aynı kredi-yetersiz/iade davranışı. Ayrı bir
|
// bedel, aynı requestId idempotency'si, aynı kredi-yetersiz/iade davranışı.
|
||||||
// "güncelleme" ürünü ya da indirimli yol yok — kullanıcı yeni bir liste alıyor,
|
// Ayrı bir "güncelleme" ürünü ya da indirimli yol yok — kullanıcı yeni bir
|
||||||
// bedeli de yeni liste bedeli.
|
// liste alıyor, bedeli de yeni liste bedeli. Paketli kullanıcıda o bedel 0:
|
||||||
|
// liste ve revizyon pakete dâhil (raporKredi prop'u listem-icerik.tsx'te
|
||||||
|
// koşullanır), krediler yalnız danışman sorusuna gider.
|
||||||
//
|
//
|
||||||
// Renk: modalın kabuğu marka primary'si (bg-primary/10 ikon hücresi), ana
|
// Renk: modalın kabuğu marka primary'si (bg-primary/10 ikon hücresi), ana
|
||||||
// aksiyon ise ürünün CTA turuncusu — kilidi açan, kredi harcayan, ödemeye
|
// aksiyon ise ürünün CTA turuncusu — kilidi açan, kredi harcayan, ödemeye
|
||||||
@@ -127,6 +129,10 @@ export function TercihDegistiModali({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const krediYeter = kredi >= raporKredi;
|
const krediYeter = kredi >= raporKredi;
|
||||||
|
// Paketliye liste ve revizyon dâhil olduğu için bedel 0 iner (raporKredi
|
||||||
|
// prop'u listem-icerik.tsx'te koşullanıyor). Tek türetilmiş bayrak: modalın
|
||||||
|
// üç kredi cümlesi buna bakar, kredi mantığı olduğu gibi kalır.
|
||||||
|
const ucretsiz = raporKredi === 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
@@ -184,8 +190,17 @@ export function TercihDegistiModali({
|
|||||||
tablosunda zaten duruyor; açıklama yalnızca sonucu ve
|
tablosunda zaten duruyor; açıklama yalnızca sonucu ve
|
||||||
bedeli söylüyor. */}
|
bedeli söylüyor. */}
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
Listen eski tercihlerinle kuruldu. Yeni liste bunun yerine
|
{ucretsiz ? (
|
||||||
geçer ve {raporKredi} kredi düşer.
|
<>
|
||||||
|
Listen eski tercihlerinle kuruldu. Yeni liste bunun yerine
|
||||||
|
geçer; güncelleme paketine dâhil, kredi düşmez.
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
Listen eski tercihlerinle kuruldu. Yeni liste bunun yerine
|
||||||
|
geçer ve {raporKredi} kredi düşer.
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -245,7 +260,7 @@ export function TercihDegistiModali({
|
|||||||
{durum.ad === "hata" ? (
|
{durum.ad === "hata" ? (
|
||||||
<p className="text-sm text-red-700">{durum.mesaj}</p>
|
<p className="text-sm text-red-700">{durum.mesaj}</p>
|
||||||
) : null}
|
) : null}
|
||||||
{!krediYeter && durum.ad !== "hata" ? (
|
{!ucretsiz && !krediYeter && durum.ad !== "hata" ? (
|
||||||
<p className="text-xs text-slate-500">
|
<p className="text-xs text-slate-500">
|
||||||
Güncelleme {raporKredi} kredi; bakiyen {kredi} kredi.
|
Güncelleme {raporKredi} kredi; bakiyen {kredi} kredi.
|
||||||
</p>
|
</p>
|
||||||
@@ -272,7 +287,9 @@ export function TercihDegistiModali({
|
|||||||
onClick={() => void guncelle()}
|
onClick={() => void guncelle()}
|
||||||
className="cursor-pointer bg-orange-500 text-white transition-[background-color,transform] duration-200 active:scale-[0.97] hover:bg-orange-600"
|
className="cursor-pointer bg-orange-500 text-white transition-[background-color,transform] duration-200 active:scale-[0.97] hover:bg-orange-600"
|
||||||
>
|
>
|
||||||
Listemi güncelle — {raporKredi} kredi
|
{ucretsiz
|
||||||
|
? "Listemi güncelle"
|
||||||
|
: `Listemi güncelle — ${raporKredi} kredi`}
|
||||||
<ArrowRight className="size-4" aria-hidden />
|
<ArrowRight className="size-4" aria-hidden />
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -149,10 +149,18 @@ async function listeOlusturKilitli(
|
|||||||
params: RaporParams,
|
params: RaporParams,
|
||||||
requestId: string,
|
requestId: string,
|
||||||
): Promise<ListeSonuc> {
|
): Promise<ListeSonuc> {
|
||||||
|
// Paket vaadi (docs/urun/vizyon.md): liste ve revizyon pakete dâhil; krediler
|
||||||
|
// yalnız danışman sorusu için. Çağrı BİLEREK duruyor — ledger'daki
|
||||||
|
// UNIQUE(reason, ref_id) (appdb/schema.ts:133) üretimin tek idempotency
|
||||||
|
// çapası; paketliye delta 0 satır yazılır, aynı requestId ikinci kez
|
||||||
|
// DUPLICATE döner. hasPaket tek yerden okunur (zaten elimizdeki user
|
||||||
|
// nesnesi) ki harcama ile iade aynı değeri görsün.
|
||||||
|
const maliyet = user.hasPaket ? 0 : RAPOR_KREDI;
|
||||||
|
|
||||||
// 3 kredi düş (idempotent: aynı requestId ile retry çifte harcamaz)
|
// 3 kredi düş (idempotent: aynı requestId ile retry çifte harcamaz)
|
||||||
const harcama = await spendCredits({
|
const harcama = await spendCredits({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
amount: RAPOR_KREDI,
|
amount: maliyet,
|
||||||
reason: "report_generate",
|
reason: "report_generate",
|
||||||
refId: requestId,
|
refId: requestId,
|
||||||
});
|
});
|
||||||
@@ -208,10 +216,13 @@ async function listeOlusturKilitli(
|
|||||||
try {
|
try {
|
||||||
sonuc = await raporUret(params);
|
sonuc = await raporUret(params);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Üretim başarısız → krediyi iade et
|
// Üretim başarısız → krediyi iade et. Satır paketlide de yazılır (delta 0):
|
||||||
|
// yukarıdaki DUPLICATE dalı "önceki deneme başarısız mıydı" sorusunu tam
|
||||||
|
// olarak bu refund kaydının varlığıyla cevaplıyor. Tutar koşullu, yoksa
|
||||||
|
// harcaması 0 olan paketliye her başarısız denemede bedava kredi yazardık.
|
||||||
await grantCredits({
|
await grantCredits({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
delta: RAPOR_KREDI,
|
delta: maliyet,
|
||||||
reason: "refund",
|
reason: "refund",
|
||||||
refId: requestId,
|
refId: requestId,
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
@@ -240,7 +251,7 @@ async function listeOlusturKilitli(
|
|||||||
rapor: user.hasPaket ? sonuc : raporMaskele(sonuc),
|
rapor: user.hasPaket ? sonuc : raporMaskele(sonuc),
|
||||||
params,
|
params,
|
||||||
revisionCount: 0,
|
revisionCount: 0,
|
||||||
kredi: user.creditBalance - RAPOR_KREDI,
|
kredi: user.creditBalance - maliyet,
|
||||||
hasPaket: user.hasPaket,
|
hasPaket: user.hasPaket,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -282,9 +293,15 @@ export async function listeRevize(input: {
|
|||||||
const params = rapor.params as RaporParams;
|
const params = rapor.params as RaporParams;
|
||||||
const onceki = rapor.result as RaporSonuc;
|
const onceki = rapor.result as RaporSonuc;
|
||||||
|
|
||||||
|
// Revizyon pakete dâhil (bkz. listeOlusturKilitli'deki aynı not). Yukarıdaki
|
||||||
|
// hasPaket kapısı yüzünden burada maliyet her zaman 0; ifade yine de koşullu
|
||||||
|
// yazılıyor ki kapı ileride gevşerse paketsiz kullanıcıdan ücret düşmeye
|
||||||
|
// devam etsin. Revizyon hakkını MAX_REVIZYON sayacı sınırlıyor, kredi değil.
|
||||||
|
const maliyet = user.hasPaket ? 0 : RAPOR_KREDI;
|
||||||
|
|
||||||
const harcama = await spendCredits({
|
const harcama = await spendCredits({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
amount: RAPOR_KREDI,
|
amount: maliyet,
|
||||||
reason: "report_revision",
|
reason: "report_revision",
|
||||||
refId: input.requestId,
|
refId: input.requestId,
|
||||||
});
|
});
|
||||||
@@ -336,9 +353,11 @@ export async function listeRevize(input: {
|
|||||||
listeOzetiCikar(onceki, params.sira),
|
listeOzetiCikar(onceki, params.sira),
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
// İade satırı burada da yazılır (paketlide delta 0) — DUPLICATE dalındaki
|
||||||
|
// "önceki deneme başarısızdı" çıkarımı buna dayanıyor.
|
||||||
await grantCredits({
|
await grantCredits({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
delta: RAPOR_KREDI,
|
delta: maliyet,
|
||||||
reason: "refund",
|
reason: "refund",
|
||||||
refId: input.requestId,
|
refId: input.requestId,
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
@@ -360,7 +379,7 @@ export async function listeRevize(input: {
|
|||||||
rapor: sonuc,
|
rapor: sonuc,
|
||||||
params,
|
params,
|
||||||
revisionCount: rapor.revisionCount + 1,
|
revisionCount: rapor.revisionCount + 1,
|
||||||
kredi: user.creditBalance - RAPOR_KREDI,
|
kredi: user.creditBalance - maliyet,
|
||||||
hasPaket: true,
|
hasPaket: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user