Commit: Bulk unfinished work

This commit is contained in:
2026-01-22 17:39:04 +01:00
parent 6c46b4efcc
commit 3a9acc42a2
68 changed files with 5047 additions and 1064 deletions

View File

@@ -0,0 +1,125 @@
package projectv1
import (
"context"
"errors"
"slices"
"connectrpc.com/connect"
"git.kocoder.xyz/kocoded/vt/fx"
projectv1 "git.kocoder.xyz/kocoded/vt/gen/project/v1"
"git.kocoder.xyz/kocoded/vt/gen/project/v1/projectv1connect"
"git.kocoder.xyz/kocoded/vt/interceptors"
"git.kocoder.xyz/kocoded/vt/model"
"git.kocoder.xyz/kocoded/vt/query"
"gorm.io/gorm"
)
func NewProjectRoute(db *gorm.DB, oidcInterceptor *interceptors.AuthenticationInterceptor) fx.Handler {
path, handler := projectv1connect.NewProjectServiceHandler(&projectService{db: db}, connect.WithInterceptors(oidcInterceptor))
return fx.NewRoute(path, handler)
}
type projectService struct{ db *gorm.DB }
// ListProjects implements projectv1connect.ProjectServiceHandler.
func (s *projectService) ListProjects(ctx context.Context, req *projectv1.ListProjectsRequest) (*projectv1.ListProjectsResponse, error) {
session, ok := interceptors.SessionFromContext(ctx)
if !ok {
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("No session set in interceptor"))
}
p := query.Use(s.db).Projekt
query := p.Where(p.MandantID.Eq(session.MandantId)).Limit(int(req.PerPage)).Offset(int(req.Page))
if req.OrberBy != "" {
f, ok := p.GetFieldByName(req.OrberBy)
if ok {
if !req.Asc {
query = query.Order(f.Desc())
} else {
query = query.Order(f.Asc())
}
}
} else {
query = query.Order(p.ID.Asc())
}
projects, err := query.Find()
if err != nil {
return nil, connect.NewError(connect.CodeUnknown, err)
}
cnt, err := p.Where(p.MandantID.Eq(session.MandantId)).Count()
if err != nil {
return nil, connect.NewError(connect.CodeUnimplemented, err)
}
data := make([]*projectv1.GetProjectResponse, len(projects))
for i, p := range projects {
data[i] = &projectv1.GetProjectResponse{
Id: int64(p.ID),
Name: p.Name,
Description: p.Description,
IsMaterialized: newPointerBoolean(true),
IsPersonalized: newPointerBoolean(true),
IsConfirmed: newPointerBoolean(true),
IsPaid: nil,
IsDone: s.IsDone(p),
}
}
return &projectv1.ListProjectsResponse{
Data: data,
Meta: &projectv1.Metadata{TotalCount: int32(cnt)},
}, nil
}
func newPointerBoolean(val bool) *bool {
b := val
return &b
}
func (s *projectService) IsDone(p *model.Projekt) *bool {
t := query.Use(s.db).Task
tasks, err := t.Where(t.ProjektID.Eq(p.ID)).Find()
if err != nil {
panic(err)
}
if len(tasks) == 0 {
return nil
}
if i := slices.IndexFunc(tasks, func(t *model.Task) bool {
return !t.Status.IsDone()
}); i != -1 {
return newPointerBoolean(false)
}
return newPointerBoolean(true)
}
func (s *projectService) GetProject(ctx context.Context, req *projectv1.GetProjectRequest) (*projectv1.GetProjectResponse, error) {
session, ok := interceptors.SessionFromContext(ctx)
if !ok {
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("No session set in interceptor"))
}
p := query.Use(s.db).Projekt
query, err := p.Where(p.ID.Eq(uint(req.Id))).Where(p.MandantID.Eq(session.MandantId)).First()
if err != nil {
return nil, err
}
return &projectv1.GetProjectResponse{
Id: int64(query.ID),
Name: query.Name,
Description: query.Description,
IsMaterialized: newPointerBoolean(true),
IsPersonalized: newPointerBoolean(true),
IsConfirmed: newPointerBoolean(true),
IsPaid: newPointerBoolean(true),
IsDone: newPointerBoolean(true),
}, nil
}

View File

@@ -0,0 +1,39 @@
syntax = "proto3";
package project.v1;
message GetProjectRequest {
int32 id = 1;
}
message GetProjectResponse {
int64 id = 1;
string name = 2;
string description = 3;
optional bool is_materialized = 5;
optional bool is_personalized = 6;
optional bool is_confirmed = 7;
optional bool is_paid = 8;
optional bool is_done = 9;
}
message ListProjectsRequest {
int32 page = 1;
int32 per_page = 2;
string orber_by = 3;
bool asc = 4;
}
message Metadata {
int32 totalCount = 1;
}
message ListProjectsResponse {
repeated GetProjectResponse data = 1;
Metadata meta = 2;
}
service ProjectService {
rpc GetProject(GetProjectRequest) returns (GetProjectResponse);
rpc ListProjects(ListProjectsRequest) returns (ListProjectsResponse);
}