summaryrefslogtreecommitdiff
path: root/internal/actions/projects.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/actions/projects.go')
-rw-r--r--internal/actions/projects.go64
1 files changed, 64 insertions, 0 deletions
diff --git a/internal/actions/projects.go b/internal/actions/projects.go
new file mode 100644
index 0000000..f991728
--- /dev/null
+++ b/internal/actions/projects.go
@@ -0,0 +1,64 @@
+package actions
+
+import (
+ "context"
+ "database/sql"
+ "fmt"
+ "strconv"
+
+ "punchcard/internal/queries"
+)
+
+// CreateProject creates a new project for the specified client
+func (a *actionsImpl) CreateProject(ctx context.Context, name, client string, billableRate *float64) (*queries.Project, error) {
+ // Find the client first
+ clientRecord, err := a.FindClient(ctx, client)
+ if err != nil {
+ return nil, fmt.Errorf("invalid client: %w", err)
+ }
+
+ var billableRateParam sql.NullInt64
+ if billableRate != nil && *billableRate > 0 {
+ rate := int64(*billableRate * 100) // Convert dollars to cents
+ billableRateParam = sql.NullInt64{Int64: rate, Valid: true}
+ }
+
+ project, err := a.queries.CreateProject(ctx, queries.CreateProjectParams{
+ Name: name,
+ ClientID: clientRecord.ID,
+ BillableRate: billableRateParam,
+ })
+ if err != nil {
+ return nil, fmt.Errorf("failed to create project: %w", err)
+ }
+
+ return &project, nil
+}
+
+// FindProject finds a project by name or ID
+func (a *actionsImpl) FindProject(ctx context.Context, nameOrID string) (*queries.Project, error) {
+ // Parse as ID if possible, otherwise use 0
+ var idParam int64
+ if id, err := strconv.ParseInt(nameOrID, 10, 64); err == nil {
+ idParam = id
+ }
+
+ // Search by both ID and name
+ projects, err := a.queries.FindProject(ctx, queries.FindProjectParams{
+ ID: idParam,
+ Name: nameOrID,
+ })
+ if err != nil {
+ return nil, fmt.Errorf("database error looking up project: %w", err)
+ }
+
+ // Check results
+ switch len(projects) {
+ case 0:
+ return nil, fmt.Errorf("%w: %s", ErrProjectNotFound, nameOrID)
+ case 1:
+ return &projects[0], nil
+ default:
+ return nil, fmt.Errorf("%w: %s matches multiple projects", ErrAmbiguousProject, nameOrID)
+ }
+} \ No newline at end of file