Initial commit: dating app backend (Go/Gin/GORM/Postgres)
Phone+OTP auth, staged onboarding, admin approval workflow, and a full discovery/swipe/match/chat system with photo upload and approximate distance (haversine) based on user location. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"dating-app/internal/models"
|
||||
)
|
||||
|
||||
type UserRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewUserRepository(db *gorm.DB) *UserRepository {
|
||||
return &UserRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *UserRepository) FindByPhone(phone string) (*models.User, error) {
|
||||
var user models.User
|
||||
err := r.db.Where("phone = ?", phone).First(&user).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (r *UserRepository) FindByID(id uint) (*models.User, error) {
|
||||
var user models.User
|
||||
err := r.db.First(&user, id).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// GetOrCreateByPhone کاربر را با شمارهی دادهشده پیدا میکند یا در صورت نبود میسازد.
|
||||
func (r *UserRepository) GetOrCreateByPhone(phone string) (*models.User, bool, error) {
|
||||
var user models.User
|
||||
err := r.db.Where("phone = ?", phone).First(&user).Error
|
||||
if err == nil {
|
||||
return &user, false, nil
|
||||
}
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
user = models.User{
|
||||
Phone: phone,
|
||||
State: models.UserStateInactive,
|
||||
IsActive: true,
|
||||
CurrentStep: models.StepBasicInfo,
|
||||
}
|
||||
if err := r.db.Create(&user).Error; err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return &user, true, nil
|
||||
}
|
||||
|
||||
// ListPendingApproval کاربرانی که آنبوردینگ رو تکمیل کردن و منتظر بررسی ادمیناند
|
||||
// رو به ترتیب قدیمیترین اول برمیگردونه.
|
||||
func (r *UserRepository) ListPendingApproval() ([]models.User, error) {
|
||||
var users []models.User
|
||||
err := r.db.
|
||||
Where("is_onboarded = ? AND approval_status = ?", true, models.ApprovalPending).
|
||||
Order("updated_at asc").
|
||||
Find(&users).Error
|
||||
return users, err
|
||||
}
|
||||
|
||||
// ListDiscoverable کاندیداهای بخش دوستیابی رو برمیگردونه: تاییدشده، فعال،
|
||||
// جنسیت مخالف کاربر (بهعنوان سادهترین فرض پیشفرض؛ فیلد ترجیح جنسیتی/گرایش
|
||||
// هنوز توی سیستم وجود نداره) و کسایی که قبلاً روشون سواپ نزده.
|
||||
// چون فاصله باید توی Go محاسبه بشه (haversine)، یک batch بزرگتر از حد
|
||||
// نهایی برمیگردونه تا بعد از فیلتر فاصله همچنان گزینهی کافی بمونه.
|
||||
func (r *UserRepository) ListDiscoverable(currentUserID uint, oppositeGender models.Gender, minAge, maxAge int, batchSize int) ([]models.User, error) {
|
||||
var users []models.User
|
||||
now := time.Now()
|
||||
minBirth := now.AddDate(-maxAge-1, 0, 1)
|
||||
maxBirth := now.AddDate(-minAge, 0, 0)
|
||||
|
||||
err := r.db.
|
||||
Where("id != ?", currentUserID).
|
||||
Where("is_onboarded = ? AND approval_status = ? AND is_active = ?", true, models.ApprovalApproved, true).
|
||||
Where("gender = ?", oppositeGender).
|
||||
Where("birth_date BETWEEN ? AND ?", minBirth, maxBirth).
|
||||
Where("NOT EXISTS (SELECT 1 FROM swipes s WHERE s.swiper_id = ? AND s.swiped_id = users.id)", currentUserID).
|
||||
Order("id asc").
|
||||
Limit(batchSize).
|
||||
Find(&users).Error
|
||||
return users, err
|
||||
}
|
||||
|
||||
func (r *UserRepository) Save(user *models.User) error {
|
||||
return r.db.Save(user).Error
|
||||
}
|
||||
|
||||
func (r *UserRepository) UpdateFields(user *models.User, fields map[string]interface{}) error {
|
||||
return r.db.Model(user).Updates(fields).Error
|
||||
}
|
||||
|
||||
func (r *UserRepository) DB() *gorm.DB {
|
||||
return r.db
|
||||
}
|
||||
Reference in New Issue
Block a user