feat(in-kind): varlık türleri, fiyat tablosu, aynî borç/alacak, birikim planı ve ödeme akışı, 008 migration

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-05 12:37:48 +03:00
parent 1062b2d96c
commit 9781cd9ed2
15 changed files with 1354 additions and 3 deletions
+64
View File
@@ -0,0 +1,64 @@
import { describe, expect, it } from "vitest";
import {
formatAssetQuantity,
inKindProgress,
quantityForAmount,
valuationPrice,
valueOf,
} from "./assets";
describe("varlık hesapları", () => {
it("değer ve miktar karşılığı (binde bir miktar, kuruş fiyat)", () => {
// 5 gr × 3.250,50 TL = 16.252,50 TL
expect(valueOf(5_000, 3_250_50)).toBe(16_252_50);
expect(valueOf(1_500, 100_00)).toBe(150_00);
expect(quantityForAmount(16_252_50, 3_250_50)).toBe(5_000);
expect(quantityForAmount(100, 0)).toBe(0);
});
it("biçim", () => {
expect(formatAssetQuantity("gram_gold", 5_000)).toBe("5 gr Gram altın (24 ayar)");
expect(formatAssetQuantity("quarter_gold", 2_000)).toBe("2 adet Çeyrek altın");
expect(formatAssetQuantity("usd", 1_500_000)).toBe("1.500 USD");
expect(formatAssetQuantity("bracelet_22k", 12_345)).toBe("12,345 gr 22 ayar bilezik");
});
it("değerleme fiyatı: borç satış, alacak alış", () => {
const p = { buyMinor: 3_200_00, sellMinor: 3_300_00 };
expect(valuationPrice("debt", p)).toBe(3_300_00);
expect(valuationPrice("receivable", p)).toBe(3_200_00);
expect(valuationPrice("debt", null)).toBeNull();
});
});
describe("aynî borç ilerlemesi", () => {
const base = {
quantity: 5_000,
paidQuantity: 0,
unitPriceMinor: 3_000_00,
contributedMinor: 6_000_00,
spentMinor: 0,
monthlyPlanMinor: 2_000_00,
today: "2026-11-05",
};
it("kalan ihtiyaç ve tahmini kapanış ayı", () => {
// 5 gr × 3.000 = 15.000; biriken 6.000 → 9.000 kaldı; ayda 2.000 → 5 ay → 2027-04
expect(inKindProgress(base)).toEqual({
remainingQuantity: 5_000,
currentValueMinor: 15_000_00,
accumulatedMinor: 6_000_00,
remainingNeedMinor: 9_000_00,
estimatedCloseMonth: "2027-04",
});
});
it("kısmi ödeme, birikim yeterli, fiyat yok, plan yok", () => {
expect(inKindProgress({ ...base, paidQuantity: 3_000 }).remainingNeedMinor).toBe(0);
expect(inKindProgress({ ...base, paidQuantity: 3_000 }).estimatedCloseMonth).toBe("2026-11");
expect(inKindProgress({ ...base, unitPriceMinor: null }).remainingNeedMinor).toBeNull();
expect(inKindProgress({ ...base, monthlyPlanMinor: null }).estimatedCloseMonth).toBeNull();
expect(inKindProgress({ ...base, paidQuantity: 5_000 }).remainingQuantity).toBe(0);
expect(inKindProgress({ ...base, spentMinor: 9_000_00 }).accumulatedMinor).toBe(0);
});
});