MIF_E31222379_BE/internal/collector/collector_repository.go

338 lines
10 KiB
Go

package collector
import (
"context"
"fmt"
"rijig/model"
"gorm.io/gorm"
)
type CollectorRepository interface {
Create(ctx context.Context, collector *model.Collector) error
GetByID(ctx context.Context, id string) (*model.Collector, error)
GetByUserID(ctx context.Context, userID string) (*model.Collector, error)
Update(ctx context.Context, collector *model.Collector) error
Delete(ctx context.Context, UserID string) error
List(ctx context.Context, limit, offset int) ([]*model.Collector, int64, error)
GetActiveCollectors(ctx context.Context, limit, offset int) ([]*model.Collector, int64, error)
GetCollectorsByAddress(ctx context.Context, addressID string, limit, offset int) ([]*model.Collector, int64, error)
GetCollectorsByTrashCategory(ctx context.Context, trashCategoryID string, limit, offset int) ([]*model.Collector, int64, error)
UpdateJobStatus(ctx context.Context, id string, jobStatus string) error
UpdateRating(ctx context.Context, id string, rating float32) error
CreateAvailableTrash(ctx context.Context, availableTrash *model.AvaibleTrashByCollector) error
GetAvailableTrashByCollectorID(ctx context.Context, collectorID string) ([]*model.AvaibleTrashByCollector, error)
UpdateAvailableTrash(ctx context.Context, availableTrash *model.AvaibleTrashByCollector) error
DeleteAvailableTrash(ctx context.Context, id string) error
BulkCreateAvailableTrash(ctx context.Context, availableTrashList []*model.AvaibleTrashByCollector) error
BulkUpdateAvailableTrash(ctx context.Context, collectorID string, availableTrashList []*model.AvaibleTrashByCollector) error
DeleteAvailableTrashByCollectorID(ctx context.Context, collectorID string) error
WithTx(tx *gorm.DB) CollectorRepository
}
type collectorRepository struct {
db *gorm.DB
}
func NewCollectorRepository(db *gorm.DB) CollectorRepository {
return &collectorRepository{
db: db,
}
}
func (r *collectorRepository) WithTx(tx *gorm.DB) CollectorRepository {
return &collectorRepository{
db: tx,
}
}
func (r *collectorRepository) Create(ctx context.Context, collector *model.Collector) error {
if err := r.db.WithContext(ctx).Create(collector).Error; err != nil {
return fmt.Errorf("failed to create collector: %w", err)
}
return nil
}
func (r *collectorRepository) GetByID(ctx context.Context, id string) (*model.Collector, error) {
var collector model.Collector
err := r.db.WithContext(ctx).
Preload("Address").
Preload("AvaibleTrashByCollector").
Preload("AvaibleTrashByCollector.TrashCategory").
Where("id = ?", id).
First(&collector).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, fmt.Errorf("collector with id %s not found", id)
}
return nil, fmt.Errorf("failed to get collector by id: %w", err)
}
return &collector, nil
}
func (r *collectorRepository) GetByUserID(ctx context.Context, userID string) (*model.Collector, error) {
var collector model.Collector
err := r.db.WithContext(ctx).
Preload("Address").
Preload("AvaibleTrashByCollector").
Preload("AvaibleTrashByCollector.TrashCategory").
Where("user_id = ?", userID).
First(&collector).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, fmt.Errorf("collector with user_id %s not found", userID)
}
return nil, fmt.Errorf("failed to get collector by user_id: %w", err)
}
return &collector, nil
}
func (r *collectorRepository) Update(ctx context.Context, collector *model.Collector) error {
if err := r.db.WithContext(ctx).Save(collector).Error; err != nil {
return fmt.Errorf("failed to update collector: %w", err)
}
return nil
}
func (r *collectorRepository) Delete(ctx context.Context, UserID string) error {
result := r.db.WithContext(ctx).Delete(&model.Collector{}, "user_id = ?", UserID)
if result.Error != nil {
return fmt.Errorf("failed to delete collector: %w", result.Error)
}
if result.RowsAffected == 0 {
return fmt.Errorf("collector with user_id %s not found", UserID)
}
return nil
}
func (r *collectorRepository) List(ctx context.Context, limit, offset int) ([]*model.Collector, int64, error) {
var collectors []*model.Collector
var total int64
if err := r.db.WithContext(ctx).Model(&model.Collector{}).Count(&total).Error; err != nil {
return nil, 0, fmt.Errorf("failed to count collectors: %w", err)
}
err := r.db.WithContext(ctx).
Preload("Address").
Preload("AvaibleTrashByCollector").
Preload("AvaibleTrashByCollector.TrashCategory").
Limit(limit).
Offset(offset).
Find(&collectors).Error
if err != nil {
return nil, 0, fmt.Errorf("failed to list collectors: %w", err)
}
return collectors, total, nil
}
func (r *collectorRepository) GetActiveCollectors(ctx context.Context, limit, offset int) ([]*model.Collector, int64, error) {
var collectors []*model.Collector
var total int64
query := r.db.WithContext(ctx).Where("job_status = ?", "active")
if err := query.Model(&model.Collector{}).Count(&total).Error; err != nil {
return nil, 0, fmt.Errorf("failed to count active collectors: %w", err)
}
err := query.
Preload("Address").
Preload("AvaibleTrashByCollector").
Preload("AvaibleTrashByCollector.TrashCategory").
Limit(limit).
Offset(offset).
Find(&collectors).Error
if err != nil {
return nil, 0, fmt.Errorf("failed to get active collectors: %w", err)
}
return collectors, total, nil
}
func (r *collectorRepository) GetCollectorsByAddress(ctx context.Context, addressID string, limit, offset int) ([]*model.Collector, int64, error) {
var collectors []*model.Collector
var total int64
query := r.db.WithContext(ctx).Where("address_id = ?", addressID)
if err := query.Model(&model.Collector{}).Count(&total).Error; err != nil {
return nil, 0, fmt.Errorf("failed to count collectors by address: %w", err)
}
err := query.
Preload("Address").
Preload("AvaibleTrashByCollector").
Preload("AvaibleTrashByCollector.TrashCategory").
Limit(limit).
Offset(offset).
Find(&collectors).Error
if err != nil {
return nil, 0, fmt.Errorf("failed to get collectors by address: %w", err)
}
return collectors, total, nil
}
func (r *collectorRepository) GetCollectorsByTrashCategory(ctx context.Context, trashCategoryID string, limit, offset int) ([]*model.Collector, int64, error) {
var collectors []*model.Collector
var total int64
subQuery := r.db.WithContext(ctx).
Table("avaible_trash_by_collectors").
Select("collector_id").
Where("trash_category_id = ?", trashCategoryID)
query := r.db.WithContext(ctx).
Where("id IN (?)", subQuery)
if err := query.Model(&model.Collector{}).Count(&total).Error; err != nil {
return nil, 0, fmt.Errorf("failed to count collectors by trash category: %w", err)
}
err := query.
Preload("Address").
Preload("AvaibleTrashByCollector").
Preload("AvaibleTrashByCollector.TrashCategory").
Limit(limit).
Offset(offset).
Find(&collectors).Error
if err != nil {
return nil, 0, fmt.Errorf("failed to get collectors by trash category: %w", err)
}
return collectors, total, nil
}
func (r *collectorRepository) UpdateJobStatus(ctx context.Context, id string, jobStatus string) error {
result := r.db.WithContext(ctx).
Model(&model.Collector{}).
Where("id = ?", id).
Update("job_status", jobStatus)
if result.Error != nil {
return fmt.Errorf("failed to update job status: %w", result.Error)
}
if result.RowsAffected == 0 {
return fmt.Errorf("collector with id %s not found", id)
}
return nil
}
func (r *collectorRepository) UpdateRating(ctx context.Context, id string, rating float32) error {
result := r.db.WithContext(ctx).
Model(&model.Collector{}).
Where("id = ?", id).
Update("rating", rating)
if result.Error != nil {
return fmt.Errorf("failed to update rating: %w", result.Error)
}
if result.RowsAffected == 0 {
return fmt.Errorf("collector with id %s not found", id)
}
return nil
}
func (r *collectorRepository) CreateAvailableTrash(ctx context.Context, availableTrash *model.AvaibleTrashByCollector) error {
if err := r.db.WithContext(ctx).Create(availableTrash).Error; err != nil {
return fmt.Errorf("failed to create available trash: %w", err)
}
return nil
}
func (r *collectorRepository) GetAvailableTrashByCollectorID(ctx context.Context, collectorID string) ([]*model.AvaibleTrashByCollector, error) {
var availableTrash []*model.AvaibleTrashByCollector
err := r.db.WithContext(ctx).
Preload("TrashCategory").
Where("collector_id = ?", collectorID).
Find(&availableTrash).Error
if err != nil {
return nil, fmt.Errorf("failed to get available trash by collector id: %w", err)
}
return availableTrash, nil
}
func (r *collectorRepository) UpdateAvailableTrash(ctx context.Context, availableTrash *model.AvaibleTrashByCollector) error {
if err := r.db.WithContext(ctx).Save(availableTrash).Error; err != nil {
return fmt.Errorf("failed to update available trash: %w", err)
}
return nil
}
func (r *collectorRepository) DeleteAvailableTrash(ctx context.Context, id string) error {
result := r.db.WithContext(ctx).Delete(&model.AvaibleTrashByCollector{}, "id = ?", id)
if result.Error != nil {
return fmt.Errorf("failed to delete available trash: %w", result.Error)
}
if result.RowsAffected == 0 {
return fmt.Errorf("available trash with id %s not found", id)
}
return nil
}
func (r *collectorRepository) BulkCreateAvailableTrash(ctx context.Context, availableTrashList []*model.AvaibleTrashByCollector) error {
if len(availableTrashList) == 0 {
return nil
}
if err := r.db.WithContext(ctx).CreateInBatches(availableTrashList, 100).Error; err != nil {
return fmt.Errorf("failed to bulk create available trash: %w", err)
}
return nil
}
func (r *collectorRepository) BulkUpdateAvailableTrash(ctx context.Context, collectorID string, availableTrashList []*model.AvaibleTrashByCollector) error {
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
if err := tx.Where("collector_id = ?", collectorID).Delete(&model.AvaibleTrashByCollector{}).Error; err != nil {
return fmt.Errorf("failed to delete existing available trash: %w", err)
}
if len(availableTrashList) > 0 {
for _, item := range availableTrashList {
item.CollectorID = collectorID
}
if err := tx.CreateInBatches(availableTrashList, 100).Error; err != nil {
return fmt.Errorf("failed to create new available trash: %w", err)
}
}
return nil
})
}
func (r *collectorRepository) DeleteAvailableTrashByCollectorID(ctx context.Context, collectorID string) error {
if err := r.db.WithContext(ctx).Where("collector_id = ?", collectorID).Delete(&model.AvaibleTrashByCollector{}).Error; err != nil {
return fmt.Errorf("failed to delete available trash by collector id: %w", err)
}
return nil
}