WIP: Keep writing projectS

Signed-off-by: Nikolai Rodionov <iam@allanger.xyz>
This commit is contained in:
2026-05-20 13:37:48 +02:00
parent 121e3f2664
commit 0cf8aefc1c
5 changed files with 202 additions and 17 deletions

View File

@@ -10,8 +10,9 @@ import (
)
var (
ErrAlreadyExists = errors.New("entry already exists")
ErrNotFound = errors.New("entry not found")
ErrAlreadyExists = errors.New("entry already exists")
ErrCheckNotPassed = errors.New("sql checks not passed")
ErrNotFound = errors.New("entry not found")
)
type AccountData struct {

View File

@@ -3,7 +3,11 @@ package repository
import (
"context"
"database/sql"
"errors"
"time"
"github.com/jackc/pgerrcode"
"github.com/jackc/pgx/v5/pgconn"
)
type ProjectData struct {
@@ -13,7 +17,7 @@ type ProjectData struct {
Description string
CreatedBy string
CreatedAt time.Time
ArchivedAt sql.NullTime
ClosedAt sql.NullTime
Blocked bool
UpdatedAt time.Time
UpdatedBy string
@@ -23,18 +27,67 @@ type ProjectData struct {
func CreateProject(ctx context.Context, db *sql.DB, data *ProjectData) error {
query := `
INSERT INTO projects
(uuid, name, slug, )
(uuid, name, slug, description, owner_user_id, billing_account_id, created_by, created_at, updated_by, updated_at)
VALUES
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
`
if _, err := db.ExecContext(ctx, query,
data.UUID, data.Name, data.Slug, data.Description, data.CreatedBy,
data.CreatedBy, data.CreatedBy, data.CreatedAt, data.CreatedBy, data.CreatedAt); err != nil {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
switch pgErr.Code {
case pgerrcode.UniqueViolation:
return ErrAlreadyExists
case pgerrcode.CheckViolation:
return ErrCheckNotPassed
}
return err
}
return err
}
return nil
}
// GetProjectByID returns a project from the database
func GetProjectByID(ctx context.Context, db *sql.DB, projectID string) (data *ProjectData, err error) {
return nil, nil
func GetProjectByID(ctx context.Context, db *sql.DB, projectID string) (*ProjectData, error) {
data := &ProjectData{}
query := `
SELECT uuid, name, slug, description, owner_user_id, closed_at, created_at
FROM projects
WHERE uuid=$1`
if err := db.QueryRowContext(ctx, query, projectID).Scan(
&data.UUID,
&data.Name,
&data.Slug,
&data.Description,
&data.CreatedBy,
&data.ClosedAt,
&data.CreatedAt,
); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrNotFound
}
return nil, err
}
return data, nil
}
// UpdateProject change editable project data
func UpdateProject(ctx context.Context, db *sql.DB, data *ProjectData) error {
query := `
UPDATE projects
SET
name = $2,
description = $3,
updated_at = $4,
updated_by = $5
WHERE uuid = $1;`
if _, err := db.Query(query, data.UUID, data.Name, data.Description, data.UpdatedAt, data.UpdatedBy); err != nil {
return err
}
return nil
}

View File

@@ -7,20 +7,127 @@ import (
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/repository"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)
func TestProjectsRepository_Success(t *testing.T) {
func TestIntegrationProjectsCreate_Success(t *testing.T) {
createdBy := uuid.NewString()
_ = &repository.ProjectData{
project := &repository.ProjectData{
UUID: uuid.NewString(),
Name: "test-1",
Slug: "test_1",
Slug: uuid.NewString(),
Description: "Test Project Number 1",
CreatedBy: createdBy,
CreatedAt: time.Now(),
ArchivedAt: sql.NullTime{Time: time.Now()},
ClosedAt: sql.NullTime{Time: time.Now()},
Blocked: false,
UpdatedAt: time.Now(),
UpdatedBy: createdBy,
}
assert.NoError(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project))
}
func TestIntegrationProjectsCreate_CheckFailed(t *testing.T) {
createdBy := uuid.NewString()
project := &repository.ProjectData{
UUID: uuid.NewString(),
Name: "test-2",
Slug: "test_2",
Description: "Test Project Number 1",
CreatedBy: createdBy,
CreatedAt: time.Now(),
ClosedAt: sql.NullTime{Time: time.Now()},
Blocked: false,
UpdatedAt: time.Now(),
UpdatedBy: createdBy,
}
assert.Error(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project), repository.ErrCheckNotPassed)
}
func TestIntegrationProjectsCreate_AlreadyExistsFail(t *testing.T) {
createdBy := uuid.NewString()
project := &repository.ProjectData{
UUID: uuid.NewString(),
Name: "test-3",
Slug: uuid.NewString(),
Description: "Test Project Number 1",
CreatedBy: createdBy,
CreatedAt: time.Now(),
ClosedAt: sql.NullTime{Time: time.Now()},
Blocked: false,
UpdatedAt: time.Now(),
UpdatedBy: createdBy,
}
assert.NoError(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project))
assert.Error(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project), repository.ErrAlreadyExists)
}
func TestIntegrationProjectsCreateAndGet_Success(t *testing.T) {
createdBy := uuid.NewString()
project := &repository.ProjectData{
UUID: uuid.NewString(),
Name: "test-4",
Slug: uuid.NewString(),
Description: "Test Project Number 1",
CreatedBy: createdBy,
CreatedAt: time.Now(),
Blocked: false,
UpdatedAt: time.Now(),
UpdatedBy: createdBy,
}
assert.NoError(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project))
data, err := repository.GetProjectByID(t.Context(), newTestDBConnection(t.Context()), project.UUID)
assert.NoError(t, err)
assert.Equal(t, project.Name, data.Name)
assert.Equal(t, project.Slug, data.Slug)
assert.Equal(t, project.Description, data.Description)
assert.Equal(t, project.CreatedBy, data.CreatedBy)
assert.Equal(t, project.ClosedAt.Time.Truncate(time.Second), data.ClosedAt.Time.Truncate(time.Second))
assert.Equal(t, project.CreatedAt.Truncate(time.Second), data.CreatedAt.Truncate(time.Second))
}
func TestIntegrationProjectsCreateAndGet_NotFound(t *testing.T) {
data, err := repository.GetProjectByID(t.Context(), newTestDBConnection(t.Context()), uuid.NewString())
assert.ErrorIs(t, err, repository.ErrNotFound)
assert.Nil(t, data)
}
func TestIntegrationProjectsCreateUpdateAndGet_Success(t *testing.T) {
createdBy := uuid.NewString()
project := &repository.ProjectData{
UUID: uuid.NewString(),
Name: "test-5",
Slug: uuid.NewString(),
Description: "Test Project Number 1",
CreatedBy: createdBy,
CreatedAt: time.Now(),
Blocked: false,
UpdatedAt: time.Now(),
UpdatedBy: createdBy,
}
assert.NoError(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project))
data, err := repository.GetProjectByID(t.Context(), newTestDBConnection(t.Context()), project.UUID)
assert.NoError(t, err)
assert.Equal(t, project.Name, data.Name)
assert.Equal(t, project.Slug, data.Slug)
assert.Equal(t, project.Description, data.Description)
assert.Equal(t, project.CreatedBy, data.CreatedBy)
assert.Equal(t, project.ClosedAt.Time.Truncate(time.Second), data.ClosedAt.Time.Truncate(time.Second))
assert.Equal(t, project.CreatedAt.Truncate(time.Second), data.CreatedAt.Truncate(time.Second))
project.UpdatedBy = uuid.NewString()
project.UpdatedAt = time.Now()
project.Description = "Updated description"
project.Name = "update name"
assert.NoError(t, repository.UpdateProject(t.Context(), newTestDBConnection(t.Context()), project))
data, err = repository.GetProjectByID(t.Context(), newTestDBConnection(t.Context()), project.UUID)
assert.NoError(t, err)
assert.Equal(t, project.Name, data.Name)
assert.Equal(t, project.Slug, data.Slug)
assert.Equal(t, project.Description, data.Description)
}