From 20216116f126619f66ea79cf7269ec1796e9a8c8 Mon Sep 17 00:00:00 2001
From: Cecilentsama <Cecile.ntsama@student.reutlingen-university.de>
Date: Tue, 27 May 2025 17:34:46 +0200
Subject: [PATCH] resolving path errors

---
 src/app/project/projects.go              | 246 +++++++++++++++++++++++
 src/app/project/repository/repository.go |   0
 2 files changed, 246 insertions(+)
 create mode 100644 src/app/project/projects.go
 create mode 100644 src/app/project/repository/repository.go

diff --git a/src/app/project/projects.go b/src/app/project/projects.go
new file mode 100644
index 0000000..daa2d9b
--- /dev/null
+++ b/src/app/project/projects.go
@@ -0,0 +1,246 @@
+package project
+
+import (
+	"context"
+	"errors"
+	"time"
+
+	"github.com/google/uuid"
+	"github.com/jackc/pgx/v5/pgxpool"
+	"github.com/org-harmony/harmony/src/core/trace"
+	"github.com/org-harmony/harmony/src/core/validation"
+)
+
+// Errors that can be defined in the module
+var (
+	ErrProjectNotFound       = errors.New("project not found")
+	ErrProjectAlreadyExists  = errors.New("project already exists")
+	ErrInvalidProject        = errors.New("invalid project data")
+	ErrProjectUpdateFailed   = errors.New("failed to update project")
+	ErrProjectDeleteFailed   = errors.New("failed to delete project")
+	ErrProjectCreationFailed = errors.New("failed to create project")
+)
+
+// Project represents a project in the system
+type Project struct {
+	ID          uuid.UUID `json:"id"`
+	Name        string    `json:"name"`
+	Description string    `json:"description"`
+	OwnerID     uuid.UUID `json:"owner_id"`
+	Status      string    `json:"status"`
+	CreatedAt   time.Time `json:"created_at"`
+	UpdatedAt   time.Time `json:"updated_at"`
+}
+
+// NewProject creates a new instance of Project
+func NewProject(name, description string, ownerID uuid.UUID, status string) *Project {
+	now := time.Now()
+	return &Project{
+		ID:          uuid.New(),
+		Name:        name,
+		Description: description,
+		OwnerID:     ownerID,
+		Status:      status,
+		CreatedAt:   now,
+		UpdatedAt:   now,
+	}
+}
+
+// Service defines operations available for projects
+type Service interface {
+	Create(ctx context.Context, project *Project) error
+	GetByID(ctx context.Context, id uuid.UUID) (*Project, error)
+	Edit(ctx context.Context, project *Project) error
+	Delete(ctx context.Context, id uuid.UUID) error
+	List(ctx context.Context, ownerID uuid.UUID) ([]*Project, error)
+}
+
+type service struct {
+	repo      Repository
+	validator validation.V
+	logger    trace.Logger
+}
+
+func NewService(repo Repository, validator validation.V, logger trace.Logger) Service {
+	return &service{
+		repo:      repo,
+		validator: validator,
+		logger:    logger,
+	}
+}
+
+func (s *service) Create(ctx context.Context, project *Project) error {
+	if err := s.validator.Struct(project); err != nil {
+		s.logger.Error("Invalid project data", "error", err)
+		return ErrInvalidProject
+	}
+	if err := s.repo.Create(ctx, project); err != nil {
+		s.logger.Error("Failed to create project", "error", err)
+		return ErrProjectCreationFailed
+	}
+	return nil
+}
+
+func (s *service) GetByID(ctx context.Context, id uuid.UUID) (*Project, error) {
+	project, err := s.repo.GetByID(ctx, id)
+	if err != nil {
+		s.logger.Error("Failed to get project", "error", err, "id", id)
+		return nil, ErrProjectNotFound
+	}
+	return project, nil
+}
+
+func (s *service) Edit(ctx context.Context, project *Project) error {
+	return s.Update(ctx, project)
+}
+
+func (s *service) Update(ctx context.Context, project *Project) error {
+	if err := s.validator.Struct(project); err != nil {
+		s.logger.Error("Invalid project data", "error", err)
+		return ErrInvalidProject
+	}
+	project.UpdatedAt = time.Now()
+	if err := s.repo.Update(ctx, project); err != nil {
+		s.logger.Error("Failed to update project", "error", err)
+		return ErrProjectUpdateFailed
+	}
+	return nil
+}
+
+func (s *service) Delete(ctx context.Context, id uuid.UUID) error {
+	if err := s.repo.Delete(ctx, id); err != nil {
+		s.logger.Error("Failed to delete project", "error", err, "id", id)
+		return ErrProjectDeleteFailed
+	}
+	return nil
+}
+
+func (s *service) List(ctx context.Context, ownerID uuid.UUID) ([]*Project, error) {
+	projects, err := s.repo.List(ctx, ownerID)
+	if err != nil {
+		s.logger.Error("Failed to list projects", "error", err, "ownerID", ownerID)
+		return nil, err
+	}
+	return projects, nil
+}
+
+// Repository defines persistence operations for projects
+type Repository interface {
+	Create(ctx context.Context, project *Project) error
+	GetByID(ctx context.Context, id uuid.UUID) (*Project, error)
+	Update(ctx context.Context, project *Project) error
+	Delete(ctx context.Context, id uuid.UUID) error
+	List(ctx context.Context, ownerID uuid.UUID) ([]*Project, error)
+	RepositoryName() string
+}
+
+type repository struct {
+	db *pgxpool.Pool
+}
+
+func NewRepository(db *pgxpool.Pool) Repository {
+	return &repository{db: db}
+}
+
+func (r *repository) RepositoryName() string {
+	return "project"
+}
+
+func (r *repository) Create(ctx context.Context, project *Project) error {
+	query := `
+		INSERT INTO projects (id, name, description, owner_id, status, created_at, updated_at)
+		VALUES ($1, $2, $3, $4, $5, $6, $7)
+	`
+	_, err := r.db.Exec(ctx, query,
+		project.ID,
+		project.Name,
+		project.Description,
+		project.OwnerID,
+		project.Status,
+		project.CreatedAt,
+		project.UpdatedAt,
+	)
+	return err
+}
+
+func (r *repository) GetByID(ctx context.Context, id uuid.UUID) (*Project, error) {
+	query := `
+		SELECT id, name, description, owner_id, status, created_at, updated_at
+		FROM projects
+		WHERE id = $1
+	`
+	var project Project
+	err := r.db.QueryRow(ctx, query, id).Scan(
+		&project.ID,
+		&project.Name,
+		&project.Description,
+		&project.OwnerID,
+		&project.Status,
+		&project.CreatedAt,
+		&project.UpdatedAt,
+	)
+	if err != nil {
+		return nil, err
+	}
+	return &project, nil
+}
+
+func (r *repository) Update(ctx context.Context, project *Project) error {
+	query := `
+		UPDATE projects
+		SET name = $1, description = $2, status = $3, updated_at = $4
+		WHERE id = $5
+	`
+	_, err := r.db.Exec(ctx, query,
+		project.Name,
+		project.Description,
+		project.Status,
+		project.UpdatedAt,
+		project.ID,
+	)
+	return err
+}
+
+func (r *repository) Delete(ctx context.Context, id uuid.UUID) error {
+	query := "DELETE FROM projects WHERE id = $1"
+	_, err := r.db.Exec(ctx, query, id)
+	return err
+}
+
+func (r *repository) List(ctx context.Context, ownerID uuid.UUID) ([]*Project, error) {
+	query := `
+		SELECT id, name, description, owner_id, status, created_at, updated_at
+		FROM projects
+		WHERE owner_id = $1
+		ORDER BY created_at DESC
+	`
+	rows, err := r.db.Query(ctx, query, ownerID)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+
+	var projects []*Project
+	for rows.Next() {
+		var project Project
+		err := rows.Scan(
+			&project.ID,
+			&project.Name,
+			&project.Description,
+			&project.OwnerID,
+			&project.Status,
+			&project.CreatedAt,
+			&project.UpdatedAt,
+		)
+		if err != nil {
+			return nil, err
+		}
+		projects = append(projects, &project)
+	}
+
+	if err := rows.Err(); err != nil {
+		return nil, err
+	}
+
+	return projects, nil
+}
diff --git a/src/app/project/repository/repository.go b/src/app/project/repository/repository.go
new file mode 100644
index 0000000..e69de29
-- 
GitLab