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:
@@ -0,0 +1,61 @@
|
||||
import { model, models, Schema, type InferSchemaType, type Model } from "mongoose";
|
||||
import { ASSET_KEYS } from "@/shared/assets";
|
||||
|
||||
/**
|
||||
* Aynî borç/alacak (Bölüm 6.5): bir cariyle altın, ziynet veya döviz cinsinden borç.
|
||||
* Borç tarihi fiyatı ve TL karşılığı not olarak saklanır; güncel değer fiyat tablosundan.
|
||||
* Kapanış yalnızca "Ödeme gerçekleşti" kayıtlarıyla (kısmi ödeme miktarı düşürür).
|
||||
* Birikim planı: katkılar seçilen birikim hesabına transferdir (`transactions.inKindDebtId`).
|
||||
*/
|
||||
const paymentSchema = new Schema(
|
||||
{
|
||||
date: { type: String, required: true },
|
||||
/** asset: aynı varlıkla · cash: TL karşılığıyla. */
|
||||
method: { type: String, enum: ["asset", "cash"], required: true },
|
||||
quantity: { type: Number, required: true, min: 1 },
|
||||
/** Ödemede harcanan / tahsil edilen TL (aynı varlıkla ödemede varlığı almak için harcanan). */
|
||||
amountMinor: { type: Number, default: 0, min: 0 },
|
||||
accountId: { type: Schema.Types.ObjectId, default: null },
|
||||
transactionId: { type: Schema.Types.ObjectId, default: null },
|
||||
note: { type: String, default: "", maxlength: 300 },
|
||||
createdBy: { type: Schema.Types.ObjectId, required: true },
|
||||
},
|
||||
{ _id: true, timestamps: { createdAt: true, updatedAt: false } },
|
||||
);
|
||||
|
||||
const inKindDebtSchema = new Schema(
|
||||
{
|
||||
householdId: { type: Schema.Types.ObjectId, required: true },
|
||||
contactId: { type: Schema.Types.ObjectId, required: true },
|
||||
/** debt: ben borçluyum · receivable: bana borçlu. */
|
||||
direction: { type: String, enum: ["debt", "receivable"], required: true },
|
||||
assetKey: { type: String, enum: ASSET_KEYS, required: true },
|
||||
/** Binde bir (5 gr → 5000). */
|
||||
quantity: { type: Number, required: true, min: 1 },
|
||||
date: { type: String, required: true },
|
||||
unitPriceMinor: { type: Number, default: null },
|
||||
valueMinor: { type: Number, default: null },
|
||||
note: { type: String, default: "", maxlength: 500 },
|
||||
savingsAccountId: { type: Schema.Types.ObjectId, default: null },
|
||||
monthlyPlanMinor: { type: Number, default: null },
|
||||
payments: { type: [paymentSchema], default: [] },
|
||||
closedAt: { type: String, default: null },
|
||||
deletedAt: { type: Date, default: null },
|
||||
seedRef: { type: String, default: null },
|
||||
createdBy: { type: Schema.Types.ObjectId, required: true },
|
||||
updatedBy: { type: Schema.Types.ObjectId, required: true },
|
||||
},
|
||||
{ timestamps: true, collection: "inKindDebts" },
|
||||
);
|
||||
|
||||
inKindDebtSchema.index({ householdId: 1, contactId: 1, deletedAt: 1 });
|
||||
inKindDebtSchema.index(
|
||||
{ householdId: 1, seedRef: 1 },
|
||||
{ unique: true, partialFilterExpression: { seedRef: { $type: "string" } } },
|
||||
);
|
||||
|
||||
export type InKindDebt = InferSchemaType<typeof inKindDebtSchema>;
|
||||
|
||||
export const InKindDebtModel: Model<InKindDebt> =
|
||||
(models.InKindDebt as Model<InKindDebt> | undefined) ??
|
||||
model<InKindDebt>("InKindDebt", inKindDebtSchema);
|
||||
Reference in New Issue
Block a user