Skip to content
Open
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
148 changes: 0 additions & 148 deletions internal/commands/account_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"math"
"os"
"sort"
"strings"
"text/tabwriter"

Expand Down Expand Up @@ -61,53 +60,6 @@ func newAccountProfileCmd() *cobra.Command {
return c
}

// printProfileTable renders a user profile API response as a key-value table.
func printProfileTable(v any) error {
profile, ok := v.(map[string]any)
if !ok {
return printJSON(v)
}

// Build Name from fullName.firstName + lastName.
name := "—"
if fn, ok := profile["fullName"].(map[string]any); ok {
first := cellValue(fn["firstName"])
last := cellValue(fn["lastName"])
parts := []string{}
if first != "—" {
parts = append(parts, first)
}
if last != "—" {
parts = append(parts, last)
}
if len(parts) > 0 {
name = strings.Join(parts, " ")
}
}

// Extract registeredAt as YYYY-MM-DD.
registered := cellValue(profile["registeredAt"])
if len(registered) >= 10 {
registered = registered[:10]
}

w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
rows := []struct{ label, value string }{
{"Name", name},
{"Email", cellValue(profile["email"])},
{"Phone", cellValue(profile["phoneNumber"])},
{"Postcode", cellValue(profile["postcode"])},
{"Language", cellValue(profile["language"])},
{"Profile", cellValue(profile["profileType"])},
{"Adult", cellValue(profile["isAdult"])},
{"Registered", registered},
}
for _, r := range rows {
_, _ = fmt.Fprintf(w, "%s\t%s\n", r.label, r.value)
}
return w.Flush()
}

func newAccountAddressesCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "addresses",
Expand Down Expand Up @@ -146,31 +98,6 @@ func newAccountAddressesListCmd() *cobra.Command {
return c
}

// printAddressesTable renders a shipping address list as a tabwriter table.
func printAddressesTable(v any) error {
list, ok := v.([]any)
if !ok {
return printJSON(v)
}
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
_, _ = fmt.Fprintln(w, "id\trecipient\tstreet\tcity\tpostcode\tphone")
for _, item := range list {
row, ok := item.(map[string]any)
if !ok {
continue
}
id := cellValue(row["id"])
addr, _ := row["shippingAddress"].(map[string]any)
recipient := cellValue(addr["recipient"])
street := formatStreet(addr)
city := cellValue(addr["city"])
postcode := cellValue(addr["postcode"])
phone := cellValue(addr["phoneNumber"])
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n", id, recipient, street, city, postcode, phone)
}
return w.Flush()
}

// formatStreet builds a human-readable street string from an address map.
func formatStreet(addr map[string]any) string {
if addr == nil {
Expand Down Expand Up @@ -366,21 +293,6 @@ func fetchConsents(s *session.Session, uid string) (map[string]any, error) {
return consents, nil
}

// printConsentsTable renders a consent key→bool map as a sorted tabwriter table.
func printConsentsTable(consents map[string]any) error {
keys := make([]string, 0, len(consents))
for k := range consents {
keys = append(keys, k)
}
sort.Strings(keys)
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
_, _ = fmt.Fprintln(w, "key\tenabled")
for _, k := range keys {
_, _ = fmt.Fprintf(w, "%s\t%v\n", k, consents[k])
}
return w.Flush()
}

func newAccountConsentsUpdateCmd() *cobra.Command {
var userID, payloadFile string
c := &cobra.Command{
Expand Down Expand Up @@ -482,40 +394,6 @@ func newAccountPaymentsCmd() *cobra.Command {
return c
}

// printPaymentsTable renders a paginated payments API response as a tabwriter table.
func printPaymentsTable(v any) error {
page, ok := v.(map[string]any)
if !ok {
return printJSON(v)
}

// Pagination info.
pageIndex := int(toFloat(page["pageIndex"]))
pageCount := int(toFloat(page["pageCount"]))
totalCount := int(toFloat(page["totalCount"]))
fmt.Printf("Page %d/%d (%d total)\n\n", pageIndex, pageCount, totalCount)

items := toSlice(page["items"])
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
_, _ = fmt.Fprintln(w, "date\tstatus\tchannel\tcard\torderId")
for _, item := range items {
row, ok := item.(map[string]any)
if !ok {
continue
}
date := cellValue(row["createdAt"])
if len(date) >= 10 {
date = date[:10]
}
status := cellValue(row["status"])
channel := cellValue(row["channelName"])
card := cellValue(row["creditCardBrand"])
orderID := cellValue(row["orderId"])
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", date, status, channel, card, orderID)
}
return w.Flush()
}

func newAccountMembershipCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "membership",
Expand Down Expand Up @@ -685,32 +563,6 @@ func newAccountMembershipPointsHistoryCmd() *cobra.Command {
return c
}

// printPointsHistoryTable renders a paginated membership points response as a tabwriter table.
func printPointsHistoryTable(v any) error {
page, ok := v.(map[string]any)
if !ok {
return printJSON(v)
}
items := toSlice(page["items"])
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
_, _ = fmt.Fprintln(w, "date\toperation\tpoints\torderId")
for _, item := range items {
row, ok := item.(map[string]any)
if !ok {
continue
}
date := cellValue(row["createdAt"])
if len(date) >= 10 {
date = date[:10]
}
operation := cellValue(row["operation"])
points := cellValue(row["membershipPoints"])
orderID := cellValue(row["orderId"])
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", date, operation, points, orderID)
}
return w.Flush()
}

// toFloat coerces a numeric any value to float64, returning 0 for unrecognised types.
func toFloat(v any) float64 {
switch n := v.(type) {
Expand Down
164 changes: 0 additions & 164 deletions internal/commands/cart_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package commands
import (
"fmt"
"os"
"sort"
"strings"
"text/tabwriter"

Expand Down Expand Up @@ -107,169 +106,6 @@ type cartItem struct {
pricePerKg float64
}

func printCartSummary(v any, opts cartShowOpts) error {
root, ok := v.(map[string]any)
if !ok {
return fmt.Errorf("unexpected cart payload")
}
rawProducts, ok := root["products"].([]any)
if !ok {
return fmt.Errorf("missing products list")
}

// Build normalised items.
items := make([]cartItem, 0, len(rawProducts))
for _, raw := range rawProducts {
entry, ok := raw.(map[string]any)
if !ok {
continue
}
pid := asString(entry["productId"])
qty := asInt(entry["quantity"])

var product map[string]any
if p, ok := entry["product"].(map[string]any); ok {
product = p
}

name := shared.ProductNameFromMap(product)
if name == "" {
name = pid
}

// grammage and unit from product
grammage := ""
unit := ""
if product != nil {
if g, ok := product["grammage"].(string); ok {
grammage = strings.TrimSpace(g)
}
if u, ok := product["unitOfMeasure"].(string); ok {
unit = strings.TrimSpace(u)
}
}

// unit price: prefer item-level price, fall back to product price
unitPriceStr := shared.MoneyString(entry["price"])
if unitPriceStr == "" && product != nil {
unitPriceStr = shared.MoneyString(product["price"])
}
unitPrice, _ := parseMoneyFloat(unitPriceStr)

// total
totalStr := shared.MoneyString(entry["total"])
var lineTotal float64
if totalStr != "" {
lineTotal, _ = parseMoneyFloat(totalStr)
} else if unitPrice > 0 && qty > 0 {
lineTotal = unitPrice * float64(qty)
}

// price per kg/litre — calculated when unit is weight/volume based
pricePerKg := 0.0
unitNorm := strings.ToLower(unit)
if unitNorm == "kilogram" || unitNorm == "litre" {
if g, ok := parseGrammageKg(grammage); ok && g > 0 && unitPrice > 0 {
pricePerKg = unitPrice / g
}
}
// also try pricePerUnit from product map as a direct fallback
if pricePerKg == 0 && product != nil {
if pkObj, ok := product["pricePerUnit"].(map[string]any); ok {
if pv, ok := pkObj["price"].(float64); ok {
pricePerKg = pv
}
}
if pricePerKg == 0 {
if pv, ok := product["pricePerKg"].(float64); ok {
pricePerKg = pv
}
}
}

items = append(items, cartItem{
pid: pid,
name: name,
qty: qty,
grammage: grammage,
unit: unit,
unitPrice: unitPrice,
total: lineTotal,
pricePerKg: pricePerKg,
})
}

// Sort.
switch strings.ToLower(strings.TrimSpace(opts.sortBy)) {
case "total":
sort.SliceStable(items, func(i, j int) bool {
return items[i].total > items[j].total
})
case "price-per-kg":
sort.SliceStable(items, func(i, j int) bool {
a, b := items[i].pricePerKg, items[j].pricePerKg
if a == 0 {
return false
}
if b == 0 {
return true
}
return a > b
})
case "name":
sort.SliceStable(items, func(i, j int) bool {
return strings.ToLower(items[i].name) < strings.ToLower(items[j].name)
})
}

// Limit.
if opts.top > 0 && opts.top < len(items) {
items = items[:opts.top]
}

// Print table.
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
_, _ = fmt.Fprintln(w, "NAME\tPRODUCT ID\tQTY\tGRAMMAGE\tUNIT\tUNIT PRICE\tPRICE/KG\tTOTAL")
grandTotal := 0.0
for _, it := range items {
ppkgStr := "-"
if it.pricePerKg > 0 {
ppkgStr = fmt.Sprintf("%.2f", it.pricePerKg)
}
unitPriceStr := "-"
if it.unitPrice > 0 {
unitPriceStr = fmt.Sprintf("%.2f", it.unitPrice)
}
totalStr := "-"
if it.total > 0 {
totalStr = fmt.Sprintf("%.2f", it.total)
grandTotal += it.total
}
_, _ = fmt.Fprintf(
w,
"%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\n",
shared.TruncateText(it.name, 48),
it.pid,
it.qty,
fallbackDash(it.grammage),
fallbackDash(it.unit),
unitPriceStr,
ppkgStr,
totalStr,
)
}
_ = w.Flush()

if totalByStore, ok := root["total"].(map[string]any); ok {
if val := shared.MoneyString(totalByStore["_total"]); val != "" {
_, _ = fmt.Printf("\nCart total: %s\n", val)
}
} else if grandTotal > 0 {
_, _ = fmt.Printf("\nCart total: %.2f\n", grandTotal)
}
return nil
}

// parseGrammageKg parses a grammage string like "500 g", "1 kg", "250ml", "1.5 l"
// and returns the value in kilograms (or litres, treated equally).
func parseGrammageKg(s string) (float64, bool) {
Expand Down
Loading
Loading