package main import ( "encoding/json" "fmt" "io" "os" "regexp" "strconv" "text/tabwriter" "github.com/alecthomas/kong" "git.samanthony.xyz/lulu" ) var ( pkgIdExpr = regexp.MustCompile( `[0-9]{4}X[0-9]{4}\.[A-Z]{2}\.[A-Z]{3}\.[A-Z]{2}\.[A-Z0-9]{5,8}\.[A-Z]{3}`) printJobCostLineItemExpr = regexp.MustCompile( `([1-9][0-9]*)x_(` + pkgIdExpr.String() + `)_p([1-9][0-9]*)`) printJobCostLineItemFmt = `ITEM: 'x_' '_p' : positive number : run 'lulu list mfg' for valid values : positive number E.g., "10x_0600X0900.BW.STD.PB.060UW444.MXX_p250" is 10 copies with these manufacturing options and 250 pages.` ) type CostCmd struct { ShippingAddress Ship lulu.ShippingLevel `required help:"${ship_level_help}"` Items []PrintJobCostLineItem `required help:"${cost_item_help}"` } func (cmd *CostCmd) Run(cli *kong.Kong, clnt *lulu.Client) error { items := make([]lulu.PrintJobCostLineItem, len(cmd.Items)) for i := range cmd.Items { items[i] = cmd.Items[i].PrintJobCostLineItem } cost, addrVal, err := clnt.PrintJobCost(items, cmd.ShippingAddress.Addr(), cmd.Ship) if err != nil { return err } if len(addrVal.Warnings) > 0 { j, err := json.Marshal(addrVal) if err != nil { cli.Fatalf("%v\n", err) } cli.Errorf("%s\n", j) } w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) printCost(w, cost) return w.Flush() } type PrintJobCostLineItem struct { lulu.PrintJobCostLineItem } func (item *PrintJobCostLineItem) UnmarshalText(text []byte) error { s := string(text) groups := printJobCostLineItemExpr.FindStringSubmatch(s) if len(groups) != 4 { return fmt.Errorf("malformed %T: %q", *item, s) } quantity, err := strconv.ParseUint(groups[1], 10, 32) if err != nil { return fmt.Errorf("invalid quantity in %T %q: %w", *item, s, err) } item.Quantity = uint(quantity) if err := item.Mfg.UnmarshalText([]byte(groups[2])); err != nil { return fmt.Errorf("invalid %T in %T %q: %w", item.Mfg, *item, s, err) } npages, err := strconv.ParseUint(groups[3], 10, 32) if err != nil { return fmt.Errorf("invalid number of pages in %T %q: %w", *item, s, err) } item.NPages = uint(npages) return nil } func printCost(w io.Writer, cost lulu.PrintJobCost) { for _, fee := range cost.Fees { fmt.Fprintf(w, "fee %s %s:\t%s %s\t\n", fee.Type, fee.Sku, fee.TotalCostExclTax, fee.Currency) } for i, item := range cost.LineItemCosts { fmt.Fprintf(w, "item-%d:\t%s %s\t\n", i, item.TotalCostExclTax, cost.Currency) } fmt.Fprintf(w, "shipping:\t%s %s\t\n", cost.ShipCost.TotalCostExclTax, cost.Currency) fmt.Fprintf(w, "fulfillment:\t%s %s\t\n", cost.FulfillmentCost.TotalCostExclTax, cost.Currency) fmt.Fprintf(w, "discount:\t%s %s\t\n", cost.TotalDiscount, cost.Currency) fmt.Fprintf(w, "tax:\t%s %s\t\n", cost.TotalTax, cost.Currency) fmt.Fprintf(w, "total:\t%s %s\t\n", cost.TotalCostInclTax, cost.Currency) }