first commit

This commit is contained in:
Alkim Ake Gozen 2026-05-23 11:59:45 +09:00
commit 8b790b7601
86 changed files with 6348 additions and 0 deletions

114
ui_kits/web/data.js Normal file
View file

@ -0,0 +1,114 @@
// Sample bilingual data for the Akefin web dashboard prototype.
window.AKEFIN_DATA = (() => {
const transactions = [
{ id: "t01", date: "2026-03-02", payee: "스타벅스 강남역점", payeeNote: "Starbucks Gangnam", amount: -38500, ccy: "KRW", entity: "personal", suggestedAccount: "Personal:Expenses:Food:Coffee", score: 0.94, tier: "llm", sourceAccount: "Toss · 신한 입출금", status: "staged" },
{ id: "t02", date: "2026-03-02", payee: "이마트 트레이더스", payeeNote: "E-Mart Traders", amount: -124300, ccy: "KRW", entity: "personal", suggestedAccount: "Personal:Expenses:Groceries", score: 0.78, tier: "agent", sourceAccount: "Toss · 신한 입출금", status: "staged" },
{ id: "t03", date: "2026-03-03", payee: "Wise · Finacode partner", payeeNote: null, amount: 1240, ccy: "EUR", entity: "finacode", suggestedAccount: null, score: null, tier: "unmatched",sourceAccount: "Wise · personal", status: "staged" },
{ id: "t04", date: "2026-03-03", payee: "9TFox 컨설팅 — 클라이언트 A", payeeNote: "Consulting income", amount: 2400000, ccy: "KRW", entity: "tfox", suggestedAccount: "9TFox:Income:Consulting", score: 1.00, tier: "rules", sourceAccount: "Kakao Bank · 9TFox", status: "staged" },
{ id: "t05", date: "2026-03-04", payee: "GS25 역삼점", payeeNote: "GS25 convenience", amount: -4800, ccy: "KRW", entity: "personal", suggestedAccount: "Personal:Expenses:Convenience", score: 0.92, tier: "llm", sourceAccount: "Toss · 신한 입출금", status: "staged" },
{ id: "t06", date: "2026-03-04", payee: "관리비 — 서초 오피스텔", payeeNote: "Apartment maintenance", amount: -286000, ccy: "KRW", entity: "personal", suggestedAccount: "Personal:Expenses:Housing:Maint", score: 0.71, tier: "agent", sourceAccount: "Toss · 신한 입출금", status: "staged" },
{ id: "t07", date: "2026-03-05", payee: "Migros · İstanbul Beşiktaş", payeeNote: null, amount: -892, ccy: "TRY", entity: "personal", suggestedAccount: "Personal:Expenses:Groceries", score: 0.88, tier: "llm", sourceAccount: "Garanti BBVA", status: "staged" },
{ id: "t08", date: "2026-03-05", payee: "JR 동일본 — Suica 충전", payeeNote: "JR East · Suica", amount: -3000, ccy: "JPY", entity: "personal", suggestedAccount: "Personal:Expenses:Transit", score: 0.81, tier: "llm", sourceAccount: "Wise · multi-currency", status: "staged" },
{ id: "t09", date: "2026-03-06", payee: "배달의민족", payeeNote: "Baemin · food delivery", amount: -22600, ccy: "KRW", entity: "personal", suggestedAccount: "Personal:Expenses:Food:Delivery", score: 0.96, tier: "rules", sourceAccount: "Toss · 신한 입출금", status: "staged" },
{ id: "t10", date: "2026-03-06", payee: "노션 — 월 구독", payeeNote: "Notion subscription", amount: -16000, ccy: "KRW", entity: "tfox", suggestedAccount: "9TFox:Expenses:Software", score: 0.97, tier: "rules", sourceAccount: "Kakao Bank · 9TFox", status: "staged" },
{ id: "t11", date: "2026-03-07", payee: "MAVI Jeans · Levent", payeeNote: null, amount: -1840, ccy: "TRY", entity: "personal", suggestedAccount: "Personal:Expenses:Clothing", score: 0.68, tier: "agent", sourceAccount: "Garanti BBVA", status: "staged" },
{ id: "t12", date: "2026-03-07", payee: "Hetzner Online GmbH", payeeNote: "Server hosting", amount: -29.40, ccy: "EUR", entity: "tfox", suggestedAccount: "9TFox:Expenses:Infrastructure", score: 0.99, tier: "rules", sourceAccount: "Wise · 9TFox", status: "staged" },
{ id: "t13", date: "2026-03-08", payee: "ATM 출금 — 강남역", payeeNote: "Cash withdrawal", amount: -100000, ccy: "KRW", entity: "personal", suggestedAccount: null, score: 0.42, tier: "unmatched",sourceAccount: "Toss · 신한 입출금", status: "staged" },
];
const ruleSuggestions = [
{ id: "r01", pattern: '스타벅스 *', target: "Personal:Expenses:Food:Coffee", occurrences: 14, score: 0.97, examples: ["2026-03-02 스타벅스 강남역점 38,500 KRW", "2026-02-28 스타벅스 판교점 6,300 KRW", "2026-02-24 스타벅스 양재점 7,100 KRW"] },
{ id: "r02", pattern: '배달의민족', target: "Personal:Expenses:Food:Delivery", occurrences: 22, score: 0.99, examples: ["2026-03-06 배달의민족 22,600 KRW", "2026-02-19 배달의민족 18,400 KRW"] },
{ id: "r03", pattern: 'Hetzner *', target: "9TFox:Expenses:Infrastructure", occurrences: 6, score: 0.98, examples: ["2026-03-07 Hetzner Online GmbH 29.40 EUR", "2026-02-07 Hetzner Online GmbH 29.40 EUR"] },
{ id: "r04", pattern: 'GS25 *', target: "Personal:Expenses:Convenience", occurrences: 19, score: 0.88, examples: ["2026-03-04 GS25 역삼점 4,800 KRW", "2026-03-01 GS25 강남점 3,200 KRW"] },
{ id: "r05", pattern: 'Wise · *partner', target: "Finacode:Income:PartnerShare", occurrences: 3, score: 0.74, examples: ["2026-03-03 Wise · Finacode partner +1,240 EUR", "2026-02-03 Wise · Finacode partner +1,180 EUR"] },
];
const accountsByEntity = {
personal: [
{ path: "Personal:Assets", balance: 24830000, ccy: "KRW", kind: "branch" },
{ path: "Personal:Assets:Bank:Toss", balance: 14200000, ccy: "KRW", kind: "leaf" },
{ path: "Personal:Assets:Bank:Garanti", balance: 62400, ccy: "TRY", kind: "leaf" },
{ path: "Personal:Assets:Bank:Wise", balance: 2840, ccy: "EUR", kind: "leaf" },
{ path: "Personal:Expenses", balance: -942000, ccy: "KRW", kind: "branch" },
{ path: "Personal:Expenses:Food:Coffee", balance: -84600, ccy: "KRW", kind: "leaf" },
{ path: "Personal:Expenses:Food:Delivery", balance: -224000, ccy: "KRW", kind: "leaf" },
{ path: "Personal:Expenses:Groceries", balance: -481600, ccy: "KRW", kind: "leaf" },
{ path: "Personal:Expenses:Transit", balance: -38000, ccy: "KRW", kind: "leaf" },
],
tfox: [
{ path: "9TFox:Assets", balance: 18400000, ccy: "KRW", kind: "branch" },
{ path: "9TFox:Assets:Bank:Kakao", balance: 18400000, ccy: "KRW", kind: "leaf" },
{ path: "9TFox:Income:Consulting", balance: -7200000, ccy: "KRW", kind: "leaf" },
{ path: "9TFox:Expenses:Software", balance: 96000, ccy: "KRW", kind: "leaf" },
{ path: "9TFox:Expenses:Infrastructure", balance: 176.4, ccy: "EUR", kind: "leaf" },
],
finacode: [
{ path: "Finacode:Assets", balance: 6320, ccy: "EUR", kind: "branch" },
{ path: "Finacode:Income:PartnerShare", balance: -3700, ccy: "EUR", kind: "leaf" },
],
};
const importRuns = [
{ id: "i01", at: "2026-03-08 09:14", source: "Toss · 신한 입출금", rows: 247, auto: 153, high: 44, review: 35, failed: 15, entity: "personal" },
{ id: "i02", at: "2026-03-07 18:02", source: "Kakao Bank · 9TFox", rows: 62, auto: 58, high: 3, review: 1, failed: 0, entity: "tfox" },
{ id: "i03", at: "2026-03-07 12:48", source: "Wise · 9TFox", rows: 14, auto: 12, high: 2, review: 0, failed: 0, entity: "tfox" },
{ id: "i04", at: "2026-03-06 22:01", source: "Garanti BBVA", rows: 89, auto: 61, high: 14, review: 11, failed: 3, entity: "personal" },
];
const entities = [
{ id: "all", label: "All entities", short: "ALL", short2: "—" },
{ id: "personal", label: "Personal", short: "P/", color: "#3D6E70" },
{ id: "tfox", label: "9TFox", short: "9T/", color: "#B4541A" },
{ id: "finacode", label: "Finacode", short: "FC/", color: "#5A4FA3" },
];
// Common chart-of-accounts for the picker (sorted)
const allAccounts = [
...accountsByEntity.personal, ...accountsByEntity.tfox, ...accountsByEntity.finacode
].map(a => a.path).sort();
// FX rates (against KRW, the home currency) — sampled rates as of 2026-03-08
const fx = {
KRW: 1,
EUR: 1456.20,
TRY: 41.32,
JPY: 9.21,
USD: 1339.50,
};
const convert = (amount, fromCcy, toCcy) => {
if (fromCcy === toCcy) return amount;
return (amount * fx[fromCcy]) / fx[toCcy];
};
// Commands for the ⌘K palette
const commands = [
{ id: "approve", label: "Approve current", kind: "action", hint: "⏎", icon: "check" },
{ id: "override", label: "Override category", kind: "action", hint: "⌘E", icon: "rule" },
{ id: "skip", label: "Skip and re-queue", kind: "action", hint: "⌫", icon: "x" },
{ id: "approve-all-high", label: "Approve all ≥ 0.85 confidence", kind: "batch", hint: "⌘⇧A", icon: "check" },
{ id: "import-csv", label: "Import Toss CSV…", kind: "action", hint: "⌘I", icon: "import" },
{ id: "poll-toss", label: "Poll Toss for new transactions", kind: "action", hint: "⌘⇧I", icon: "refresh" },
{ id: "promote-rules", label: "Promote suggested rules", kind: "action", hint: "⌘R", icon: "rule" },
{ id: "commit-ledger", label: "Commit ledger to git", kind: "action", hint: "⌘⇧G", icon: "ledger" },
{ id: "switch-personal", label: "Switch scope: Personal", kind: "nav", hint: "⌘1", icon: "card" },
{ id: "switch-9tfox", label: "Switch scope: 9TFox", kind: "nav", hint: "⌘2", icon: "card" },
{ id: "switch-finacode", label: "Switch scope: Finacode", kind: "nav", hint: "⌘3", icon: "card" },
{ id: "go-review", label: "Go to Review queue", kind: "nav", hint: "G R", icon: "activity" },
{ id: "go-rules", label: "Go to Rules", kind: "nav", hint: "G U", icon: "rule" },
{ id: "go-ledger", label: "Go to Ledger", kind: "nav", hint: "G L", icon: "ledger" },
{ id: "go-import", label: "Go to Import status", kind: "nav", hint: "G I", icon: "import" },
{ id: "toggle-theme", label: "Toggle dark theme", kind: "setting", hint: "⌘\\", icon: "card" },
{ id: "search-payee", label: "Search payee or 적요…", kind: "search", hint: "/", icon: "search" },
];
// Categories (for filter)
const categories = [
"Food:Coffee", "Food:Delivery", "Food:Restaurant", "Groceries", "Convenience",
"Transit", "Housing:Maint", "Clothing", "Software", "Infrastructure",
"Income:Consulting", "Income:PartnerShare", "Cash",
];
return { transactions, ruleSuggestions, accountsByEntity, importRuns, entities, allAccounts, fx, convert, commands, categories };
})();