Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 0 additions & 29 deletions cmd/sure-cli/root/dispatch_write_test.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,10 @@
package root

import (
"bytes"
"encoding/json"
"io"
"os"
"testing"
)

// captureStdout swaps os.Stdout for a pipe, runs fn, and returns whatever was
// written. It restores the original Stdout afterwards.
func captureStdout(t *testing.T, fn func()) string {
t.Helper()
orig := os.Stdout
r, w, err := os.Pipe()
if err != nil {
t.Fatalf("pipe: %v", err)
}
os.Stdout = w

done := make(chan struct{})
var buf bytes.Buffer
go func() {
_, _ = io.Copy(&buf, r)
close(done)
}()

fn()

_ = w.Close()
<-done
os.Stdout = orig
return buf.String()
}

func TestDispatchWrite_DryRun_POST(t *testing.T) {
out := captureStdout(t, func() {
// Reset to json format so the envelope is parseable.
Expand Down
54 changes: 11 additions & 43 deletions cmd/sure-cli/root/family_exports_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/url"

"github.com/spf13/cobra"

"github.com/we-promise/sure-cli/internal/api"
"github.com/we-promise/sure-cli/internal/output"
)
Expand All @@ -18,29 +19,19 @@ func newFamilyExportsCmd() *cobra.Command {
Short: "List family exports",
Run: func(cmd *cobra.Command, args []string) {
q := url.Values{}
if page > 0 {
q.Set("page", fmt.Sprintf("%d", page))
}
if perPage > 0 {
q.Set("per_page", fmt.Sprintf("%d", perPage))
}
path := "/api/v1/family_exports"
if encoded := q.Encode(); encoded != "" {
path = path + "?" + encoded
}
printFamilyExportGet(path)
addPagingQuery(q, page, perPage)
printGet(pathWithQuery("/api/v1/family_exports", q))
},
}
list.Flags().IntVar(&page, "page", 1, "page number")
list.Flags().IntVar(&perPage, "per-page", 25, "items per page (maps to per_page)")
addPagingFlags(list, &page, &perPage)
cmd.AddCommand(list)

cmd.AddCommand(&cobra.Command{
Use: "show <id>",
Short: "Show family export",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
printFamilyExportGet(fmt.Sprintf("/api/v1/family_exports/%s", url.PathEscape(args[0])))
printGet(fmt.Sprintf("/api/v1/family_exports/%s", url.PathEscape(args[0])))
},
})

Expand All @@ -49,15 +40,15 @@ func newFamilyExportsCmd() *cobra.Command {
Use: "create",
Short: "Queue a family export (default dry-run; use --apply to execute)",
Run: func(cmd *cobra.Command, args []string) {
path := "/api/v1/family_exports"
// Upstream Api::V1::FamilyExportsController#create ignores the body
// (it queues a job per current_resource_owner.family); send {} on
// apply and pass nil for dry-run to keep the previous envelope
// shape (no body key under request).
if !apply {
printFamilyExportDryRun("POST", path, nil)
dispatchWrite(apply, "POST", "/api/v1/family_exports", nil)
return
}
client := api.New()
var res any
r, err := client.Post(path, map[string]any{}, &res)
respond(r, err, res)
dispatchWrite(true, "POST", "/api/v1/family_exports", map[string]any{})
},
}
create.Flags().BoolVar(&apply, "apply", false, "execute the create (otherwise dry-run)")
Expand Down Expand Up @@ -86,26 +77,3 @@ func newFamilyExportsCmd() *cobra.Command {

return cmd
}

func printFamilyExportGet(path string) {
client := api.New()
var res any
r, err := client.Get(path, &res)
respond(r, err, res)
}

func printFamilyExportDryRun(method, path string, body any) {
request := map[string]any{
"method": method,
"path": path,
}
if body != nil {
request["body"] = body
}
if err := output.Print(format, output.Envelope{Data: map[string]any{
"dry_run": true,
"request": request,
}}); err != nil {
output.Fail("output_failed", err.Error(), nil)
}
}
92 changes: 13 additions & 79 deletions cmd/sure-cli/root/financial_cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"time"

"github.com/spf13/cobra"
"github.com/we-promise/sure-cli/internal/api"

"github.com/we-promise/sure-cli/internal/output"
)

Expand All @@ -16,7 +16,7 @@ func newBalanceSheetCmd() *cobra.Command {
Use: "show",
Short: "Show balance sheet",
Run: func(cmd *cobra.Command, args []string) {
printFinancialGet("/api/v1/balance_sheet")
printGet("/api/v1/balance_sheet")
},
})
return cmd
Expand All @@ -32,7 +32,7 @@ func newBalancesCmd() *cobra.Command {
Short: "List balance history records",
Run: func(cmd *cobra.Command, args []string) {
q := url.Values{}
addFinancialPagingQuery(q, page, perPage)
addPagingQuery(q, page, perPage)
if accountID != "" {
q.Set("account_id", accountID)
}
Expand All @@ -45,10 +45,10 @@ func newBalancesCmd() *cobra.Command {
if endDate != "" {
q.Set("end_date", endDate)
}
printFinancialGet(financialPathWithQuery("/api/v1/balances", q))
printGet(pathWithQuery("/api/v1/balances", q))
},
}
addFinancialPagingFlags(list, &page, &perPage)
addPagingFlags(list, &page, &perPage)
list.Flags().StringVar(&accountID, "account-id", "", "account id")
list.Flags().StringVar(&currency, "currency", "", "currency")
list.Flags().StringVar(&startDate, "start-date", "", "start date (YYYY-MM-DD)")
Expand All @@ -60,7 +60,7 @@ func newBalancesCmd() *cobra.Command {
Short: "Show balance history record",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
printFinancialGet(fmt.Sprintf("/api/v1/balances/%s", url.PathEscape(args[0])))
printGet(fmt.Sprintf("/api/v1/balances/%s", url.PathEscape(args[0])))
},
})
return cmd
Expand All @@ -72,7 +72,7 @@ func newFamilySettingsCmd() *cobra.Command {
Use: "show",
Short: "Show family settings",
Run: func(cmd *cobra.Command, args []string) {
printFinancialGet("/api/v1/family_settings")
printGet("/api/v1/family_settings")
},
})
return cmd
Expand Down Expand Up @@ -104,7 +104,7 @@ func newValuationsCmd() *cobra.Command {
Short: "List valuations",
Run: func(cmd *cobra.Command, args []string) {
q := url.Values{}
addFinancialPagingQuery(q, page, perPage)
addPagingQuery(q, page, perPage)
if accountID != "" {
q.Set("account_id", accountID)
}
Expand All @@ -114,10 +114,10 @@ func newValuationsCmd() *cobra.Command {
if endDate != "" {
q.Set("end_date", endDate)
}
printFinancialGet(financialPathWithQuery("/api/v1/valuations", q))
printGet(pathWithQuery("/api/v1/valuations", q))
},
}
addFinancialPagingFlags(list, &page, &perPage)
addPagingFlags(list, &page, &perPage)
list.Flags().StringVar(&accountID, "account-id", "", "account id")
list.Flags().StringVar(&startDate, "start-date", "", "start date (YYYY-MM-DD)")
list.Flags().StringVar(&endDate, "end-date", "", "end date (YYYY-MM-DD)")
Expand All @@ -128,7 +128,7 @@ func newValuationsCmd() *cobra.Command {
Short: "Show valuation",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
printFinancialGet(fmt.Sprintf("/api/v1/valuations/%s", url.PathEscape(args[0])))
printGet(fmt.Sprintf("/api/v1/valuations/%s", url.PathEscape(args[0])))
},
})

Expand All @@ -146,13 +146,9 @@ func newValuationsCreateCmd() *cobra.Command {
payload, err := buildValuationCreatePayload(o)
if err != nil {
output.Fail("validation_failed", err.Error(), nil)
}
path := "/api/v1/valuations"
if !o.Apply {
printFinancialDryRun("POST", path, payload)
return
}
printFinancialPost(path, payload)
dispatchWrite(o.Apply, "POST", "/api/v1/valuations", payload)
},
}
cmd.Flags().StringVar(&o.AccountID, "account-id", "", "account id (required)")
Expand All @@ -174,13 +170,9 @@ func newValuationsUpdateCmd() *cobra.Command {
payload, err := buildValuationUpdatePayload(o)
if err != nil {
output.Fail("validation_failed", err.Error(), nil)
}
path := fmt.Sprintf("/api/v1/valuations/%s", url.PathEscape(args[0]))
if !o.Apply {
printFinancialDryRun("PATCH", path, payload)
return
}
printFinancialPatch(path, payload)
dispatchWrite(o.Apply, "PATCH", fmt.Sprintf("/api/v1/valuations/%s", url.PathEscape(args[0])), payload)
},
}
cmd.Flags().StringVar(&o.Amount, "amount", "", "valuation amount")
Expand Down Expand Up @@ -235,61 +227,3 @@ func buildValuationUpdatePayload(o valuationUpdateOpts) (map[string]any, error)
}
return map[string]any{"valuation": valuation}, nil
}

func addFinancialPagingFlags(cmd *cobra.Command, page, perPage *int) {
cmd.Flags().IntVar(page, "page", 1, "page number")
cmd.Flags().IntVar(perPage, "per-page", 25, "items per page (maps to per_page)")
}

func addFinancialPagingQuery(q url.Values, page, perPage int) {
if page > 0 {
q.Set("page", fmt.Sprintf("%d", page))
}
if perPage > 0 {
q.Set("per_page", fmt.Sprintf("%d", perPage))
}
}

func financialPathWithQuery(path string, q url.Values) string {
if encoded := q.Encode(); encoded != "" {
return path + "?" + encoded
}
return path
}

func printFinancialGet(path string) {
client := api.New()
var res any
r, err := client.Get(path, &res)
respond(r, err, res)
}

func printFinancialPost(path string, body any) {
client := api.New()
var res any
r, err := client.Post(path, body, &res)
respond(r, err, res)
}

func printFinancialPatch(path string, body any) {
client := api.New()
var res any
r, err := client.Patch(path, body, &res)
respond(r, err, res)
}

func printFinancialDryRun(method, path string, body any) {
request := map[string]any{
"method": method,
"path": path,
}
if body != nil {
request["body"] = body
}
if err := output.Print(format, output.Envelope{Data: map[string]any{
"dry_run": true,
"request": request,
}}); err != nil {
output.Fail("output_failed", err.Error(), nil)
}
}
10 changes: 5 additions & 5 deletions cmd/sure-cli/root/holdings_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func newHoldingsCmd() *cobra.Command {
Short: "Show investment holding",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
printInvestmentGet(fmt.Sprintf("/api/v1/holdings/%s", url.PathEscape(args[0])))
printGet(fmt.Sprintf("/api/v1/holdings/%s", url.PathEscape(args[0])))
},
})
return cmd
Expand All @@ -30,11 +30,11 @@ func newHoldingsListCmd() *cobra.Command {
Short: "List investment holdings",
Run: func(cmd *cobra.Command, args []string) {
q := url.Values{}
addInvestmentPagingQuery(q, page, perPage)
addPagingQuery(q, page, perPage)
if accountID != "" {
q.Set("account_id", accountID)
}
addRepeatedInvestmentQuery(q, "account_ids", accountIDs)
addRepeatedQuery(q, "account_ids", accountIDs)
if date != "" {
q.Set("date", date)
}
Expand All @@ -47,10 +47,10 @@ func newHoldingsListCmd() *cobra.Command {
if securityID != "" {
q.Set("security_id", securityID)
}
printInvestmentGet(investmentPathWithQuery("/api/v1/holdings", q))
printGet(pathWithQuery("/api/v1/holdings", q))
},
}
addInvestmentPagingFlags(cmd, &page, &perPage)
addPagingFlags(cmd, &page, &perPage)
cmd.Flags().StringVar(&accountID, "account-id", "", "account id")
cmd.Flags().StringSliceVar(&accountIDs, "account-ids", nil, "account ids (repeat or comma-separated)")
cmd.Flags().StringVar(&date, "date", "", "exact holding date (YYYY-MM-DD)")
Expand Down
Loading
Loading