feat(accounts): hesaplar (KMH, kredi kartı, yemek kartı, yalnızca ben)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { model, models, Schema, type InferSchemaType, type Model } from "mongoose";
|
||||
import { ACCOUNT_TYPES, DUE_RULE_KINDS, MEAL_CARD_PROVIDERS } from "@/shared/accounts";
|
||||
import { ICON_KEYS, SWATCHES } from "@/shared/appearance";
|
||||
|
||||
/**
|
||||
* Hesap (Bölüm 6.1). Tutarlar kuruş. Bakiye işareti: varlık pozitif, kart borcu negatif.
|
||||
* Güncel bakiyenin tek doğruluk kaynağı işlemlerdir (Faz 6b); `balanceCacheMinor` yalnızca önbellek.
|
||||
*/
|
||||
const overdraftSchema = new Schema(
|
||||
{
|
||||
enabled: { type: Boolean, default: false },
|
||||
limitMinor: { type: Number, min: 0, default: 0 },
|
||||
/** Aylık faiz oranı, baz puan (4,25% → 425). */
|
||||
monthlyRateBp: { type: Number, min: 0, max: 10_000, default: null },
|
||||
statementDay: { type: Number, min: 1, max: 31, default: null },
|
||||
},
|
||||
{ _id: false },
|
||||
);
|
||||
|
||||
const creditCardSchema = new Schema(
|
||||
{
|
||||
limitMinor: { type: Number, min: 0, default: 0 },
|
||||
/** Hesap kesim günü; ayda yoksa (31) ayın son günü kullanılır (Faz 7). */
|
||||
statementDay: { type: Number, min: 1, max: 31, default: 1 },
|
||||
dueRule: {
|
||||
kind: { type: String, enum: DUE_RULE_KINDS, default: "daysAfter" },
|
||||
value: { type: Number, min: 1, max: 31, default: 10 },
|
||||
},
|
||||
/** Kart borcunun ödeneceği varsayılan hesap. */
|
||||
paymentAccountId: { type: Schema.Types.ObjectId, default: null },
|
||||
},
|
||||
{ _id: false },
|
||||
);
|
||||
|
||||
const accountSchema = new Schema(
|
||||
{
|
||||
householdId: { type: Schema.Types.ObjectId, required: true },
|
||||
name: { type: String, required: true, trim: true, maxlength: 80 },
|
||||
type: { type: String, enum: ACCOUNT_TYPES, required: true },
|
||||
institution: { type: String, trim: true, maxlength: 80, default: "" },
|
||||
mealCardProvider: { type: String, enum: [...MEAL_CARD_PROVIDERS, null], default: null },
|
||||
/** İleride döviz hesabı için; şimdilik yalnızca TRY. */
|
||||
currency: { type: String, enum: ["TRY"], default: "TRY" },
|
||||
openingBalanceMinor: { type: Number, required: true, default: 0 },
|
||||
openingDate: { type: Date, required: true },
|
||||
color: { type: String, enum: SWATCHES, default: "blue" },
|
||||
icon: { type: String, enum: ICON_KEYS, default: "wallet" },
|
||||
order: { type: Number, default: 0 },
|
||||
archivedAt: { type: Date, default: null },
|
||||
/** Hesabın sahibi kişi (hane üyesi). "Yalnızca ben" hesaplarında bakiyeyi yalnızca o görür. */
|
||||
ownerUserId: { type: Schema.Types.ObjectId, default: null },
|
||||
isPrivate: { type: Boolean, default: false },
|
||||
overdraft: { type: overdraftSchema, default: null },
|
||||
creditCard: { type: creditCardSchema, default: null },
|
||||
balanceCacheMinor: { type: Number, default: null },
|
||||
createdBy: { type: Schema.Types.ObjectId, required: true },
|
||||
updatedBy: { type: Schema.Types.ObjectId, required: true },
|
||||
},
|
||||
{ timestamps: true, collection: "accounts" },
|
||||
);
|
||||
|
||||
accountSchema.index({ householdId: 1, archivedAt: 1, order: 1 });
|
||||
|
||||
export type Account = InferSchemaType<typeof accountSchema>;
|
||||
|
||||
export const AccountModel: Model<Account> =
|
||||
(models.Account as Model<Account> | undefined) ?? model<Account>("Account", accountSchema);
|
||||
Reference in New Issue
Block a user