diff options
Diffstat (limited to 'internal/commands/add_client.go')
-rw-r--r-- | internal/commands/add_client.go | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/internal/commands/add_client.go b/internal/commands/add_client.go new file mode 100644 index 0000000..e35eba9 --- /dev/null +++ b/internal/commands/add_client.go @@ -0,0 +1,90 @@ +package commands + +import ( + "database/sql" + "fmt" + "regexp" + "strings" + + "punchcard/internal/context" + "punchcard/internal/queries" + + "github.com/spf13/cobra" +) + +func NewAddClientCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "client <name> [<email>]", + Short: "Add a new client", + Long: "Add a new client to the database. Name can include email in format 'Name <email@domain.com>'", + Args: cobra.RangeArgs(1, 2), + RunE: func(cmd *cobra.Command, args []string) error { + name, email := parseNameAndEmail(args) + + billableRateFloat, _ := cmd.Flags().GetFloat64("hourly-rate") + billableRate := int64(billableRateFloat * 100) + + q := context.GetDB(cmd.Context()) + if q == nil { + return fmt.Errorf("database not available in context") + } + + var emailParam sql.NullString + if email != "" { + emailParam = sql.NullString{String: email, Valid: true} + } + + var billableRateParam sql.NullInt64 + if billableRate > 0 { + billableRateParam = sql.NullInt64{Int64: billableRate, Valid: true} + } + + client, err := q.CreateClient(cmd.Context(), queries.CreateClientParams{ + Name: name, + Email: emailParam, + BillableRate: billableRateParam, + }) + if err != nil { + return fmt.Errorf("failed to create client: %w", err) + } + + output := fmt.Sprintf("Created client: %s", client.Name) + if client.Email.Valid { + output += fmt.Sprintf(" <%s>", client.Email.String) + } + output += fmt.Sprintf(" (ID: %d)\n", client.ID) + cmd.Print(output) + + return nil + }, + } + + cmd.Flags().Float64P("hourly-rate", "r", 0, "Default hourly billable rate for this client") + + return cmd +} + +func parseNameAndEmail(args []string) (string, string) { + nameArg := args[0] + var emailArg string + if len(args) > 1 { + emailArg = args[1] + } + + if emailArg != "" { + if matches := emailAndNameRegex.FindStringSubmatch(emailArg); matches != nil { + emailArg = strings.TrimSpace(matches[2]) + } + } + + if matches := emailAndNameRegex.FindStringSubmatch(nameArg); matches != nil { + nameArg = strings.TrimSpace(matches[1]) + if emailArg == "" { + emailArg = strings.TrimSpace(matches[2]) + } + } + + return nameArg, emailArg +} + +var emailAndNameRegex = regexp.MustCompile(`^(.+?)<([^>]+@[^>]+)>$`) |