8ab2244755
- shoppingLists koleksiyonu (ürün tipi / marka / serbest metin kalemleri), migration 015 - planShopping saf fonksiyonu: paket yuvarlama, zahmet ve hacimli cezası, teslimat, yemek kartı önceliği, ek mağaza eşiği - eşik önerileri onay/red (red stok yenilenene kadar), ürün tipine hacimli işareti - fiyat servisinde ortak loadTypeOffers; seed listeleri ve testler Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
62 lines
2.7 KiB
TypeScript
62 lines
2.7 KiB
TypeScript
import { model, models, Schema, type InferSchemaType, type Model } from "mongoose";
|
||
import {
|
||
SHOPPING_ITEM_KINDS,
|
||
SHOPPING_ITEM_SOURCES,
|
||
SHOPPING_LIST_STATUSES,
|
||
} from "@/shared/shopping";
|
||
|
||
/**
|
||
* Alışveriş kalemi (Bölüm 6.12): ürün tipi (genel), belirli ürün (marka/paket) ya da serbest metin.
|
||
* Miktar binde bir: ürün tipinde tipin biriminde, üründe paket adedi, serbest metinde `unit` ile.
|
||
* `checked`: alışveriş modunda sepete alındı.
|
||
*/
|
||
const shoppingItemSchema = new Schema(
|
||
{
|
||
kind: { type: String, enum: SHOPPING_ITEM_KINDS, required: true },
|
||
productTypeId: { type: Schema.Types.ObjectId, default: null },
|
||
productId: { type: Schema.Types.ObjectId, default: null },
|
||
text: { type: String, default: "", trim: true, maxlength: 120 },
|
||
/** Boşsa "1 paket" kabul edilir. */
|
||
quantity: { type: Number, default: null, min: 0 },
|
||
/** Serbest metin kaleminin birimi. */
|
||
unit: { type: String, default: "", trim: true, maxlength: 20 },
|
||
note: { type: String, default: "", trim: true, maxlength: 200 },
|
||
source: { type: String, enum: SHOPPING_ITEM_SOURCES, default: "manual" },
|
||
checked: { type: Boolean, default: false },
|
||
checkedBy: { type: Schema.Types.ObjectId, default: null },
|
||
checkedAt: { type: Date, default: null },
|
||
addedBy: { type: Schema.Types.ObjectId, required: true },
|
||
addedAt: { type: Date, default: () => new Date() },
|
||
},
|
||
{ _id: true },
|
||
);
|
||
|
||
/** Alışveriş listesi; hane içinde ortak. Birden çok aktif liste olabilir. Silme: soft delete. */
|
||
const shoppingListSchema = new Schema(
|
||
{
|
||
householdId: { type: Schema.Types.ObjectId, required: true },
|
||
name: { type: String, required: true, trim: true, maxlength: 80 },
|
||
status: { type: String, enum: SHOPPING_LIST_STATUSES, default: "active" },
|
||
note: { type: String, default: "", trim: true, maxlength: 300 },
|
||
items: { type: [shoppingItemSchema], default: [] },
|
||
completedAt: { type: Date, 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: "shoppingLists" },
|
||
);
|
||
|
||
shoppingListSchema.index({ householdId: 1, deletedAt: 1, status: 1, updatedAt: -1 });
|
||
shoppingListSchema.index(
|
||
{ householdId: 1, seedRef: 1 },
|
||
{ unique: true, partialFilterExpression: { seedRef: { $type: "string" } } },
|
||
);
|
||
|
||
export type ShoppingList = InferSchemaType<typeof shoppingListSchema>;
|
||
|
||
export const ShoppingListModel: Model<ShoppingList> =
|
||
(models.ShoppingList as Model<ShoppingList> | undefined) ??
|
||
model<ShoppingList>("ShoppingList", shoppingListSchema);
|