cc624af69f
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
83 lines
3.4 KiB
TypeScript
83 lines
3.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
||
import {
|
||
cardPeriods,
|
||
closingOnOrAfter,
|
||
dueDate,
|
||
estimateOverdraftInterest,
|
||
installmentSchedule,
|
||
minimumPayment,
|
||
minimumRateBp,
|
||
nextPeriod,
|
||
periodContaining,
|
||
} from "./card-periods";
|
||
|
||
describe("dönem hesabı", () => {
|
||
it("kesim günü dahil hesap kesim dönemine girer; ertesi gün yeni dönem", () => {
|
||
expect(periodContaining("2026-10-29", 29)).toEqual({ start: "2026-09-30", end: "2026-10-29" });
|
||
expect(periodContaining("2026-10-30", 29)).toEqual({ start: "2026-10-30", end: "2026-11-29" });
|
||
});
|
||
|
||
it("kesim günü ayda yoksa ayın son günü (31 → Şubat 28/29)", () => {
|
||
expect(closingOnOrAfter("2026-02-10", 31)).toBe("2026-02-28");
|
||
expect(periodContaining("2028-03-05", 31)).toEqual({ start: "2028-03-01", end: "2028-03-31" });
|
||
expect(periodContaining("2026-03-01", 30)).toEqual({ start: "2026-03-01", end: "2026-03-30" });
|
||
expect(periodContaining("2026-02-28", 30)).toEqual({ start: "2026-01-31", end: "2026-02-28" });
|
||
});
|
||
|
||
it("yıl dönümü ve sonraki dönem", () => {
|
||
const p = periodContaining("2026-12-31", 15);
|
||
expect(p).toEqual({ start: "2026-12-16", end: "2027-01-15" });
|
||
expect(nextPeriod(p, 15)).toEqual({ start: "2027-01-16", end: "2027-02-15" });
|
||
});
|
||
|
||
it("güncel dönem ve son ekstre; kesim günü bugün iken dönem henüz kapanmamış", () => {
|
||
expect(cardPeriods("2026-11-05", 29)).toEqual({
|
||
current: { start: "2026-10-30", end: "2026-11-29" },
|
||
statement: { start: "2026-09-30", end: "2026-10-29" },
|
||
});
|
||
expect(cardPeriods("2026-11-29", 29).current.end).toBe("2026-11-29");
|
||
});
|
||
|
||
it("son ödeme tarihi", () => {
|
||
expect(dueDate("2026-10-29", { kind: "daysAfter", value: 10 })).toBe("2026-11-08");
|
||
expect(dueDate("2026-10-29", { kind: "fixedDay", value: 9 })).toBe("2026-11-09");
|
||
expect(dueDate("2026-10-05", { kind: "fixedDay", value: 20 })).toBe("2026-10-20");
|
||
expect(dueDate("2026-01-29", { kind: "fixedDay", value: 31 })).toBe("2026-01-31");
|
||
});
|
||
});
|
||
|
||
describe("asgari ödeme", () => {
|
||
it("limite göre %20 / %40; kart bazında oran öncelikli; yukarı yuvarlama", () => {
|
||
expect(minimumRateBp(49_999_99, null)).toBe(2000);
|
||
expect(minimumRateBp(50_000_00, null)).toBe(4000);
|
||
expect(minimumRateBp(60_000_00, 2500)).toBe(2500);
|
||
expect(minimumPayment(10_000_01, 2000)).toBe(2_000_01);
|
||
expect(minimumPayment(-5, 2000)).toBe(0);
|
||
});
|
||
});
|
||
|
||
describe("taksit planı", () => {
|
||
it("eşit bölme (kuruş farkı ilk taksitlerde), aylık tarihler, ay sonu", () => {
|
||
const s = installmentSchedule("2026-01-31", 10_000_00, 3);
|
||
expect(s.map((x) => x.amountMinor)).toEqual([3_333_34, 3_333_33, 3_333_33]);
|
||
expect(s.reduce((a, x) => a + x.amountMinor, 0)).toBe(10_000_00);
|
||
expect(s.map((x) => x.date)).toEqual(["2026-01-31", "2026-02-28", "2026-03-31"]);
|
||
});
|
||
});
|
||
|
||
describe("KMH faiz tahmini", () => {
|
||
it("gün sonu eksi bakiyeler üzerinden", () => {
|
||
const period = { start: "2026-11-01", end: "2026-11-30" };
|
||
// 10 gün boyunca -3.000 TL; sonra sıfır.
|
||
const deltas = new Map([
|
||
["2026-11-01", -3_000_00],
|
||
["2026-11-11", 3_000_00],
|
||
]);
|
||
const r = estimateOverdraftInterest(period, 0, deltas, 425);
|
||
// 10 gün × 3.000 TL × %4,25 / 30 = 42,50 TL
|
||
expect(r.interestMinor).toBe(42_50);
|
||
expect(r.days).toBe(30);
|
||
expect(estimateOverdraftInterest(period, 5_000_00, deltas, 425).interestMinor).toBe(0);
|
||
});
|
||
});
|