feat(transactions): ek bağlama, hesap ekstresi ve mutabakat servisi, 004 migration

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-05 07:55:04 +03:00
parent 2e1f4d7929
commit 2e2e33233f
15 changed files with 1049 additions and 22 deletions
+29
View File
@@ -0,0 +1,29 @@
import { z } from "zod";
import { tr } from "../../i18n/tr";
import { parseMoney } from "../money";
const v = tr.validation;
/**
* Mutabakat formu (web + mobil). `statementBalance` ekstredeki bakiye; kredi kartında
* ekstredeki BORÇ tutarı pozitif girilir (sunucu uygulamadaki eksi bakiyeye çevirir).
*/
export const reconcileSchema = z.object({
statementDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, v.date),
statementBalance: z
.string()
.trim()
.transform((s, ctx) => {
const minor = parseMoney(s);
if (minor === null) {
ctx.addIssue({ code: "custom", message: v.money });
return z.NEVER;
}
return minor;
}),
/** Fark varsa düzeltme işlemi oluşturulmasını onaylar. */
acceptAdjustment: z.boolean().default(false),
});
export type ReconcileInput = z.input<typeof reconcileSchema>;
export type ReconcileForm = z.output<typeof reconcileSchema>;
+6
View File
@@ -1,6 +1,7 @@
import { z } from "zod";
import { tr } from "../../i18n/tr";
import { parseMoney } from "../money";
import { MAX_ATTACHMENTS_PER_RECORD } from "../attachments";
import { MAX_SPLITS, normalizeTags, TRANSACTION_TYPES } from "../transactions";
const v = tr.validation;
@@ -52,6 +53,11 @@ export const transactionFormSchema = z
.union([z.string(), z.array(z.string())])
.default("")
.transform((x) => normalizeTags(x)),
/** Bağlı ek dosyalar (sıralı). Yeni ekler önce /api/files ile yüklenir. */
attachmentIds: z
.array(z.string().regex(/^[a-f0-9]{24}$/i))
.max(MAX_ATTACHMENTS_PER_RECORD, tr.attachments.errors.tooMany(MAX_ATTACHMENTS_PER_RECORD))
.default([]),
})
.superRefine((x, ctx) => {
if (x.type === "transfer") {