const mongoose = require('mongoose'); const userSchema = new mongoose.Schema({ name: { type: String, required: [true, 'Name ist erforderlich'], trim: true }, address: { type: String, required: [true, 'Adresse ist erforderlich'], trim: true }, phone: { type: String, required: [true, 'Telefonnummer ist erforderlich'], trim: true }, landline: { type: String, default: null, trim: true }, email: { type: String, default: null, trim: true, lowercase: true }, passwordHash: { type: String, default: null }, type: { type: String, required: [true, 'Typ ist erforderlich'] }, available: { type: Boolean, default: true }, gps: { lat: { type: Number, min: [-90, 'Latitude muss zwischen -90 und 90 liegen'], max: [90, 'Latitude muss zwischen -90 und 90 liegen'] }, lng: { type: Number, min: [-180, 'Longitude muss zwischen -180 und 180 liegen'], max: [180, 'Longitude muss zwischen -180 und 180 liegen'] } }, photo: { type: String, default: null }, // Soft delete fields deleted: { type: Boolean, default: false, index: true }, deletedAt: { type: Date, default: null }, deletedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'Admin', default: null }, // Stöberhundeführer invite token for initial password setup inviteToken: { type: String, default: null, select: false }, inviteTokenExpiry: { type: Date, default: null, select: false } }, { timestamps: true }); // Indexes for performance userSchema.index({ available: 1 }); userSchema.index({ type: 1 }); userSchema.index({ 'gps.lat': 1, 'gps.lng': 1 }); // Compound index for combined queries (available + type + sorting by name) userSchema.index({ available: 1, type: 1, name: 1 }); // Text index for search functionality userSchema.index({ name: 'text', address: 'text' }); // Query middleware - automatically exclude deleted documents userSchema.pre(/^find/, function(next) { // Only filter if not explicitly requesting deleted items if (!this.getOptions().includeDeleted) { this.where({ deleted: { $ne: true } }); } next(); }); module.exports = mongoose.model('User', userSchema);