mirror of
https://github.com/SamyRai/tercul-backend.git
synced 2025-12-27 05:11:34 +00:00
This commit addresses a broken build state caused by a mid-stream architectural refactoring. The changes align the existing code with the new Domain-Driven Design (DDD-lite) structure outlined in `refactor.md`. Key changes include: - Defined missing domain interfaces for `Auth`, `Localization`, and `Search`. - Refactored application services to use a `Commands` and `Queries` pattern. - Updated GraphQL resolvers to call application services instead of accessing repositories directly. - Fixed dependency injection in `cmd/api/main.go` by removing the non-existent `ApplicationBuilder` and manually instantiating services. - Corrected numerous test files (`integration`, `unit`, and `repository` tests) to reflect the new architecture, including fixing mock objects and test suite setups. - Added missing database migrations for test schemas to resolve "no such table" errors. This effort successfully gets the application to a compilable state and passes a significant portion of the test suite, laying the groundwork for further development and fixing the remaining test failures.
275 lines
12 KiB
Go
275 lines
12 KiB
Go
package domain
|
|
|
|
import (
|
|
"context"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// PaginatedResult represents a paginated result set
|
|
type PaginatedResult[T any] struct {
|
|
Items []T `json:"items"`
|
|
TotalCount int64 `json:"totalCount"`
|
|
Page int `json:"page"`
|
|
PageSize int `json:"pageSize"`
|
|
TotalPages int `json:"totalPages"`
|
|
HasNext bool `json:"hasNext"`
|
|
HasPrev bool `json:"hasPrev"`
|
|
}
|
|
|
|
// MonetizationRepository defines CRUD methods specific to Monetization.
|
|
type MonetizationRepository interface {
|
|
BaseRepository[Monetization]
|
|
AddMonetizationToWork(ctx context.Context, workID uint, monetizationID uint) error
|
|
RemoveMonetizationFromWork(ctx context.Context, workID uint, monetizationID uint) error
|
|
AddMonetizationToAuthor(ctx context.Context, authorID uint, monetizationID uint) error
|
|
RemoveMonetizationFromAuthor(ctx context.Context, authorID uint, monetizationID uint) error
|
|
AddMonetizationToBook(ctx context.Context, bookID uint, monetizationID uint) error
|
|
RemoveMonetizationFromBook(ctx context.Context, bookID uint, monetizationID uint) error
|
|
AddMonetizationToPublisher(ctx context.Context, publisherID uint, monetizationID uint) error
|
|
RemoveMonetizationFromPublisher(ctx context.Context, publisherID uint, monetizationID uint) error
|
|
AddMonetizationToSource(ctx context.Context, sourceID uint, monetizationID uint) error
|
|
RemoveMonetizationFromSource(ctx context.Context, sourceID uint, monetizationID uint) error
|
|
}
|
|
|
|
// PublisherRepository defines CRUD methods specific to Publisher.
|
|
type PublisherRepository interface {
|
|
BaseRepository[Publisher]
|
|
ListByCountryID(ctx context.Context, countryID uint) ([]Publisher, error)
|
|
}
|
|
|
|
// SourceRepository defines CRUD methods specific to Source.
|
|
type SourceRepository interface {
|
|
BaseRepository[Source]
|
|
ListByWorkID(ctx context.Context, workID uint) ([]Source, error)
|
|
FindByURL(ctx context.Context, url string) (*Source, error)
|
|
}
|
|
|
|
// BookRepository defines CRUD methods specific to Book.
|
|
type BookRepository interface {
|
|
BaseRepository[Book]
|
|
ListByAuthorID(ctx context.Context, authorID uint) ([]Book, error)
|
|
ListByPublisherID(ctx context.Context, publisherID uint) ([]Book, error)
|
|
ListByWorkID(ctx context.Context, workID uint) ([]Book, error)
|
|
FindByISBN(ctx context.Context, isbn string) (*Book, error)
|
|
}
|
|
|
|
// BookmarkRepository defines CRUD methods specific to Bookmark.
|
|
type BookmarkRepository interface {
|
|
BaseRepository[Bookmark]
|
|
ListByUserID(ctx context.Context, userID uint) ([]Bookmark, error)
|
|
ListByWorkID(ctx context.Context, workID uint) ([]Bookmark, error)
|
|
}
|
|
|
|
// CategoryRepository defines CRUD methods specific to Category.
|
|
type CategoryRepository interface {
|
|
BaseRepository[Category]
|
|
FindByName(ctx context.Context, name string) (*Category, error)
|
|
ListByWorkID(ctx context.Context, workID uint) ([]Category, error)
|
|
ListByParentID(ctx context.Context, parentID *uint) ([]Category, error)
|
|
}
|
|
|
|
// CityRepository defines CRUD methods specific to City.
|
|
type CityRepository interface {
|
|
BaseRepository[City]
|
|
ListByCountryID(ctx context.Context, countryID uint) ([]City, error)
|
|
}
|
|
|
|
// CollectionRepository defines CRUD methods specific to Collection.
|
|
type CollectionRepository interface {
|
|
BaseRepository[Collection]
|
|
ListByUserID(ctx context.Context, userID uint) ([]Collection, error)
|
|
ListPublic(ctx context.Context) ([]Collection, error)
|
|
ListByWorkID(ctx context.Context, workID uint) ([]Collection, error)
|
|
AddWorkToCollection(ctx context.Context, collectionID uint, workID uint) error
|
|
RemoveWorkFromCollection(ctx context.Context, collectionID uint, workID uint) error
|
|
}
|
|
|
|
// CommentRepository defines CRUD methods specific to Comment.
|
|
type CommentRepository interface {
|
|
BaseRepository[Comment]
|
|
ListByUserID(ctx context.Context, userID uint) ([]Comment, error)
|
|
ListByWorkID(ctx context.Context, workID uint) ([]Comment, error)
|
|
ListByTranslationID(ctx context.Context, translationID uint) ([]Comment, error)
|
|
ListByParentID(ctx context.Context, parentID uint) ([]Comment, error)
|
|
}
|
|
|
|
// ContributionRepository defines CRUD methods specific to Contribution.
|
|
type ContributionRepository interface {
|
|
BaseRepository[Contribution]
|
|
ListByUserID(ctx context.Context, userID uint) ([]Contribution, error)
|
|
ListByReviewerID(ctx context.Context, reviewerID uint) ([]Contribution, error)
|
|
ListByWorkID(ctx context.Context, workID uint) ([]Contribution, error)
|
|
ListByTranslationID(ctx context.Context, translationID uint) ([]Contribution, error)
|
|
ListByStatus(ctx context.Context, status string) ([]Contribution, error)
|
|
}
|
|
|
|
// CopyrightClaimRepository defines CRUD methods specific to CopyrightClaim.
|
|
type CopyrightClaimRepository interface {
|
|
BaseRepository[CopyrightClaim]
|
|
ListByWorkID(ctx context.Context, workID uint) ([]CopyrightClaim, error)
|
|
ListByUserID(ctx context.Context, userID uint) ([]CopyrightClaim, error)
|
|
}
|
|
|
|
// CountryRepository defines CRUD methods specific to Country.
|
|
type CountryRepository interface {
|
|
BaseRepository[Country]
|
|
GetByCode(ctx context.Context, code string) (*Country, error)
|
|
ListByContinent(ctx context.Context, continent string) ([]Country, error)
|
|
}
|
|
|
|
// EdgeRepository defines CRUD methods specific to Edge.
|
|
type EdgeRepository interface {
|
|
BaseRepository[Edge]
|
|
ListBySource(ctx context.Context, sourceTable string, sourceID uint) ([]Edge, error)
|
|
}
|
|
|
|
// EditionRepository defines CRUD methods specific to Edition.
|
|
type EditionRepository interface {
|
|
BaseRepository[Edition]
|
|
ListByBookID(ctx context.Context, bookID uint) ([]Edition, error)
|
|
FindByISBN(ctx context.Context, isbn string) (*Edition, error)
|
|
}
|
|
|
|
// EmailVerificationRepository defines CRUD methods specific to EmailVerification.
|
|
type EmailVerificationRepository interface {
|
|
BaseRepository[EmailVerification]
|
|
GetByToken(ctx context.Context, token string) (*EmailVerification, error)
|
|
GetByUserID(ctx context.Context, userID uint) ([]EmailVerification, error)
|
|
DeleteExpired(ctx context.Context) error
|
|
MarkAsUsed(ctx context.Context, id uint) error
|
|
}
|
|
|
|
// LikeRepository defines CRUD methods specific to Like.
|
|
type LikeRepository interface {
|
|
BaseRepository[Like]
|
|
ListByUserID(ctx context.Context, userID uint) ([]Like, error)
|
|
ListByWorkID(ctx context.Context, workID uint) ([]Like, error)
|
|
ListByTranslationID(ctx context.Context, translationID uint) ([]Like, error)
|
|
ListByCommentID(ctx context.Context, commentID uint) ([]Like, error)
|
|
}
|
|
|
|
// PasswordResetRepository defines CRUD methods specific to PasswordReset.
|
|
type PasswordResetRepository interface {
|
|
BaseRepository[PasswordReset]
|
|
GetByToken(ctx context.Context, token string) (*PasswordReset, error)
|
|
GetByUserID(ctx context.Context, userID uint) ([]PasswordReset, error)
|
|
DeleteExpired(ctx context.Context) error
|
|
MarkAsUsed(ctx context.Context, id uint) error
|
|
}
|
|
|
|
// PlaceRepository defines CRUD methods specific to Place.
|
|
type PlaceRepository interface {
|
|
BaseRepository[Place]
|
|
ListByCountryID(ctx context.Context, countryID uint) ([]Place, error)
|
|
ListByCityID(ctx context.Context, cityID uint) ([]Place, error)
|
|
FindNearby(ctx context.Context, latitude, longitude float64, radiusKm float64) ([]Place, error)
|
|
}
|
|
|
|
// TagRepository defines CRUD methods specific to Tag.
|
|
type TagRepository interface {
|
|
BaseRepository[Tag]
|
|
FindByName(ctx context.Context, name string) (*Tag, error)
|
|
ListByWorkID(ctx context.Context, workID uint) ([]Tag, error)
|
|
}
|
|
|
|
// TranslationRepository defines CRUD methods specific to Translation.
|
|
type TranslationRepository interface {
|
|
BaseRepository[Translation]
|
|
ListByWorkID(ctx context.Context, workID uint) ([]Translation, error)
|
|
ListByEntity(ctx context.Context, entityType string, entityID uint) ([]Translation, error)
|
|
ListByTranslatorID(ctx context.Context, translatorID uint) ([]Translation, error)
|
|
ListByStatus(ctx context.Context, status TranslationStatus) ([]Translation, error)
|
|
}
|
|
|
|
// UserRepository defines CRUD methods specific to User.
|
|
type UserRepository interface {
|
|
BaseRepository[User]
|
|
FindByUsername(ctx context.Context, username string) (*User, error)
|
|
FindByEmail(ctx context.Context, email string) (*User, error)
|
|
ListByRole(ctx context.Context, role UserRole) ([]User, error)
|
|
}
|
|
|
|
// UserProfileRepository defines CRUD methods specific to UserProfile.
|
|
type UserProfileRepository interface {
|
|
BaseRepository[UserProfile]
|
|
GetByUserID(ctx context.Context, userID uint) (*UserProfile, error)
|
|
}
|
|
|
|
// UserSessionRepository defines CRUD methods specific to UserSession.
|
|
type UserSessionRepository interface {
|
|
BaseRepository[UserSession]
|
|
GetByToken(ctx context.Context, token string) (*UserSession, error)
|
|
GetByUserID(ctx context.Context, userID uint) ([]UserSession, error)
|
|
DeleteExpired(ctx context.Context) error
|
|
}
|
|
|
|
// QueryOptions provides options for repository queries
|
|
type QueryOptions struct {
|
|
Preloads []string
|
|
OrderBy string
|
|
Where map[string]interface{}
|
|
Limit int
|
|
Offset int
|
|
}
|
|
|
|
// BaseRepository defines common CRUD operations that all repositories should implement
|
|
type BaseRepository[T any] interface {
|
|
Create(ctx context.Context, entity *T) error
|
|
CreateInTx(ctx context.Context, tx *gorm.DB, entity *T) error
|
|
GetByID(ctx context.Context, id uint) (*T, error)
|
|
GetByIDWithOptions(ctx context.Context, id uint, options *QueryOptions) (*T, error)
|
|
Update(ctx context.Context, entity *T) error
|
|
UpdateInTx(ctx context.Context, tx *gorm.DB, entity *T) error
|
|
Delete(ctx context.Context, id uint) error
|
|
DeleteInTx(ctx context.Context, tx *gorm.DB, id uint) error
|
|
List(ctx context.Context, page, pageSize int) (*PaginatedResult[T], error)
|
|
ListWithOptions(ctx context.Context, options *QueryOptions) ([]T, error)
|
|
ListAll(ctx context.Context) ([]T, error)
|
|
Count(ctx context.Context) (int64, error)
|
|
CountWithOptions(ctx context.Context, options *QueryOptions) (int64, error)
|
|
FindWithPreload(ctx context.Context, preloads []string, id uint) (*T, error)
|
|
GetAllForSync(ctx context.Context, batchSize, offset int) ([]T, error)
|
|
Exists(ctx context.Context, id uint) (bool, error)
|
|
BeginTx(ctx context.Context) (*gorm.DB, error)
|
|
WithTx(ctx context.Context, fn func(tx *gorm.DB) error) error
|
|
}
|
|
|
|
// WorkRepository defines methods specific to Work.
|
|
type WorkRepository interface {
|
|
BaseRepository[Work]
|
|
FindByTitle(ctx context.Context, title string) ([]Work, error)
|
|
FindByAuthor(ctx context.Context, authorID uint) ([]Work, error)
|
|
FindByCategory(ctx context.Context, categoryID uint) ([]Work, error)
|
|
FindByLanguage(ctx context.Context, language string, page, pageSize int) (*PaginatedResult[Work], error)
|
|
GetWithTranslations(ctx context.Context, id uint) (*Work, error)
|
|
ListWithTranslations(ctx context.Context, page, pageSize int) (*PaginatedResult[Work], error)
|
|
}
|
|
|
|
// AuthorRepository defines CRUD methods specific to Author.
|
|
type AuthorRepository interface {
|
|
BaseRepository[Author]
|
|
ListByWorkID(ctx context.Context, workID uint) ([]Author, error)
|
|
ListByBookID(ctx context.Context, bookID uint) ([]Author, error)
|
|
ListByCountryID(ctx context.Context, countryID uint) ([]Author, error)
|
|
GetWithTranslations(ctx context.Context, id uint) (*Author, error)
|
|
}
|
|
|
|
|
|
// CopyrightRepository defines CRUD methods specific to Copyright.
|
|
type CopyrightRepository interface {
|
|
BaseRepository[Copyright]
|
|
AddCopyrightToWork(ctx context.Context, workID uint, copyrightID uint) error
|
|
RemoveCopyrightFromWork(ctx context.Context, workID uint, copyrightID uint) error
|
|
AddCopyrightToAuthor(ctx context.Context, authorID uint, copyrightID uint) error
|
|
RemoveCopyrightFromAuthor(ctx context.Context, authorID uint, copyrightID uint) error
|
|
AddCopyrightToBook(ctx context.Context, bookID uint, copyrightID uint) error
|
|
RemoveCopyrightFromBook(ctx context.Context, bookID uint, copyrightID uint) error
|
|
AddCopyrightToPublisher(ctx context.Context, publisherID uint, copyrightID uint) error
|
|
RemoveCopyrightFromPublisher(ctx context.Context, publisherID uint, copyrightID uint) error
|
|
AddCopyrightToSource(ctx context.Context, sourceID uint, copyrightID uint) error
|
|
RemoveCopyrightFromSource(ctx context.Context, sourceID uint, copyrightID uint) error
|
|
AddTranslation(ctx context.Context, translation *CopyrightTranslation) error
|
|
GetTranslations(ctx context.Context, copyrightID uint) ([]CopyrightTranslation, error)
|
|
GetTranslationByLanguage(ctx context.Context, copyrightID uint, languageCode string) (*CopyrightTranslation, error)
|
|
}
|