mirror of
https://github.com/SamyRai/tercul-backend.git
synced 2025-12-27 05:11:34 +00:00
This commit marks the completion of a major refactoring effort to stabilize the codebase, improve its structure, and prepare it for production. The key changes include: - **Domain Layer Consolidation:** The `Work` entity and its related types, along with all other domain entities and repository interfaces, have been consolidated into the main `internal/domain` package. This eliminates import cycles and provides a single, coherent source of truth for the domain model. - **Data Access Layer Refactoring:** The repository implementations in `internal/data/sql` have been updated to align with the new domain layer. The `BaseRepositoryImpl` has been corrected to use pointer receivers, and all concrete repositories now correctly embed it, ensuring consistent and correct behavior. - **Application Layer Stabilization:** All application services in `internal/app` have been updated to use the new domain types and repository interfaces. Dependency injection has been corrected throughout the application, ensuring that all services are initialized with the correct dependencies. - **GraphQL Adapter Fixes:** The GraphQL resolver implementation in `internal/adapters/graphql` has been updated to correctly handle the new domain types and service methods. The auto-generated GraphQL code has been regenerated to ensure it is in sync with the schema and runtime. - **Test Suite Overhaul:** All test suites have been fixed to correctly implement their respective interfaces and use the updated domain model. Mock repositories and test suites have been corrected to properly embed the `testify` base types, resolving numerous build and linter errors. - **Dependency Management:** The Go modules have been tidied, and the module cache has been cleaned to ensure a consistent and correct dependency graph. - **Code Quality and Verification:** The entire codebase now passes all builds, tests, and linter checks, ensuring a high level of quality and stability. This comprehensive effort has resulted in a more robust, maintainable, and production-ready application.
297 lines
13 KiB
Go
297 lines
13 KiB
Go
package domain
|
|
|
|
import (
|
|
"context"
|
|
"gorm.io/gorm"
|
|
"time"
|
|
)
|
|
|
|
// 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)
|
|
ListByWorkIDPaginated(ctx context.Context, workID uint, language *string, page, pageSize int) (*PaginatedResult[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)
|
|
Upsert(ctx context.Context, translation *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
|
|
}
|
|
|
|
|
|
// 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)
|
|
}
|
|
|
|
// 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)
|
|
GetWithAssociations(ctx context.Context, id uint) (*Work, error)
|
|
GetWithAssociationsInTx(ctx context.Context, tx *gorm.DB, id uint) (*Work, error)
|
|
ListWithTranslations(ctx context.Context, page, pageSize int) (*PaginatedResult[Work], error)
|
|
IsAuthor(ctx context.Context, workID uint, authorID uint) (bool, error)
|
|
ListByCollectionID(ctx context.Context, collectionID uint) ([]Work, error)
|
|
}
|
|
|
|
// AuthRepository defines the interface for authentication data access.
|
|
type AuthRepository interface {
|
|
StoreToken(ctx context.Context, userID uint, token string, expiresAt time.Time) error
|
|
DeleteToken(ctx context.Context, token string) error
|
|
}
|
|
|
|
// LocalizationRepository defines the interface for localization data access.
|
|
type LocalizationRepository interface {
|
|
GetTranslation(ctx context.Context, key string, language string) (string, error)
|
|
GetTranslations(ctx context.Context, keys []string, language string) (map[string]string, error)
|
|
GetAuthorBiography(ctx context.Context, authorID uint, language string) (string, error)
|
|
GetWorkContent(ctx context.Context, workID uint, language string) (string, error)
|
|
}
|