mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
Repository Structure:
- Move files from cluttered root directory into organized structure
- Create archive/ for archived data and scraper results
- Create bugulma/ for the complete application (frontend + backend)
- Create data/ for sample datasets and reference materials
- Create docs/ for comprehensive documentation structure
- Create scripts/ for utility scripts and API tools
Backend Implementation:
- Implement 3 missing backend endpoints identified in gap analysis:
* GET /api/v1/organizations/{id}/matching/direct - Direct symbiosis matches
* GET /api/v1/users/me/organizations - User organizations
* POST /api/v1/proposals/{id}/status - Update proposal status
- Add complete proposal domain model, repository, and service layers
- Create database migration for proposals table
- Fix CLI server command registration issue
API Documentation:
- Add comprehensive proposals.md API documentation
- Update README.md with Users and Proposals API sections
- Document all request/response formats, error codes, and business rules
Code Quality:
- Follow existing Go backend architecture patterns
- Add proper error handling and validation
- Match frontend expected response schemas
- Maintain clean separation of concerns (handler -> service -> repository)
164 lines
4.4 KiB
Go
164 lines
4.4 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
var (
|
|
ErrNotFound = errors.New("record not found")
|
|
ErrDuplicateKey = errors.New("duplicate key violation")
|
|
ErrInvalidInput = errors.New("invalid input")
|
|
ErrVersionConflict = errors.New("version conflict - record was modified")
|
|
)
|
|
|
|
// BaseRepository provides common CRUD operations
|
|
type BaseRepository[T any] struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewBaseRepository creates a new base repository
|
|
func NewBaseRepository[T any](db *gorm.DB) *BaseRepository[T] {
|
|
return &BaseRepository[T]{db: db}
|
|
}
|
|
|
|
// Create inserts a new record
|
|
func (r *BaseRepository[T]) Create(ctx context.Context, entity *T) error {
|
|
result := r.db.WithContext(ctx).Create(entity)
|
|
if result.Error != nil {
|
|
return handleError(result.Error)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetByID retrieves a record by ID
|
|
func (r *BaseRepository[T]) GetByID(ctx context.Context, id string) (*T, error) {
|
|
var entity T
|
|
result := r.db.WithContext(ctx).First(&entity, "id = ?", id)
|
|
if result.Error != nil {
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
return nil, ErrNotFound
|
|
}
|
|
return nil, result.Error
|
|
}
|
|
return &entity, nil
|
|
}
|
|
|
|
// GetAll retrieves all records
|
|
func (r *BaseRepository[T]) GetAll(ctx context.Context) ([]*T, error) {
|
|
var entities []*T
|
|
result := r.db.WithContext(ctx).Find(&entities)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
return entities, nil
|
|
}
|
|
|
|
// Update updates an existing record
|
|
func (r *BaseRepository[T]) Update(ctx context.Context, entity *T) error {
|
|
result := r.db.WithContext(ctx).Save(entity)
|
|
if result.Error != nil {
|
|
return handleError(result.Error)
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return ErrNotFound
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Delete removes a record by ID
|
|
func (r *BaseRepository[T]) Delete(ctx context.Context, id string) error {
|
|
var entity T
|
|
result := r.db.WithContext(ctx).Delete(&entity, "id = ?", id)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return ErrNotFound
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Count returns the total number of records
|
|
func (r *BaseRepository[T]) Count() (int64, error) {
|
|
var count int64
|
|
result := r.db.Model(new(T)).Count(&count)
|
|
if result.Error != nil {
|
|
return 0, result.Error
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
// Exists checks if a record with the given ID exists
|
|
func (r *BaseRepository[T]) Exists(id string) (bool, error) {
|
|
var count int64
|
|
result := r.db.Model(new(T)).Where("id = ?", id).Count(&count)
|
|
if result.Error != nil {
|
|
return false, result.Error
|
|
}
|
|
return count > 0, nil
|
|
}
|
|
|
|
// FindWhere retrieves records matching the given conditions
|
|
func (r *BaseRepository[T]) FindWhere(query interface{}, args ...interface{}) ([]*T, error) {
|
|
return r.FindWhereWithContext(context.Background(), query, args...)
|
|
}
|
|
|
|
// FindWhereWithContext retrieves records matching the given conditions with context
|
|
func (r *BaseRepository[T]) FindWhereWithContext(ctx context.Context, query interface{}, args ...interface{}) ([]*T, error) {
|
|
var entities []*T
|
|
result := r.db.WithContext(ctx).Where(query, args...).Find(&entities)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
return entities, nil
|
|
}
|
|
|
|
// FindOneWhere retrieves a single record matching the given conditions
|
|
func (r *BaseRepository[T]) FindOneWhere(query interface{}, args ...interface{}) (*T, error) {
|
|
return r.FindOneWhereWithContext(context.Background(), query, args...)
|
|
}
|
|
|
|
// FindOneWhereWithContext retrieves a single record matching the given conditions with context
|
|
func (r *BaseRepository[T]) FindOneWhereWithContext(ctx context.Context, query interface{}, args ...interface{}) (*T, error) {
|
|
var entity T
|
|
result := r.db.WithContext(ctx).Where(query, args...).First(&entity)
|
|
if result.Error != nil {
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
return nil, ErrNotFound
|
|
}
|
|
return nil, result.Error
|
|
}
|
|
return &entity, nil
|
|
}
|
|
|
|
// Transaction executes a function within a database transaction
|
|
func (r *BaseRepository[T]) Transaction(fn func(*gorm.DB) error) error {
|
|
return r.db.Transaction(fn)
|
|
}
|
|
|
|
// DB returns the underlying GORM database instance
|
|
func (r *BaseRepository[T]) DB() *gorm.DB {
|
|
return r.db
|
|
}
|
|
|
|
// handleError converts GORM errors to repository errors
|
|
func handleError(err error) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return ErrNotFound
|
|
}
|
|
|
|
// Check for PostgreSQL duplicate key error
|
|
if errors.Is(err, gorm.ErrDuplicatedKey) {
|
|
return ErrDuplicateKey
|
|
}
|
|
|
|
return err
|
|
}
|