add export as yml_catalog
This commit is contained in:
@ -6,17 +6,21 @@ import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"git.loyso.art/frx/eway/cmd/converter/components"
|
||||
"git.loyso.art/frx/eway/cmd/cli/components"
|
||||
"git.loyso.art/frx/eway/internal/encoding/fbs"
|
||||
"git.loyso.art/frx/eway/internal/entity"
|
||||
"git.loyso.art/frx/eway/internal/export"
|
||||
|
||||
"github.com/brianvoe/gofakeit/v6"
|
||||
"github.com/rodaine/table"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/urfave/cli"
|
||||
@ -88,45 +92,8 @@ func setupCLI(ctx context.Context) *cli.App {
|
||||
app.After = releaseDI
|
||||
app.Commands = cli.Commands{
|
||||
newImportCmd(ctx),
|
||||
newExportCmd(ctx),
|
||||
newViewCmd(ctx),
|
||||
cli.Command{
|
||||
Name: "test-fbs",
|
||||
Usage: "a simple check for tbs",
|
||||
Action: cli.ActionFunc(func(c *cli.Context) error {
|
||||
gooditem := entity.GoodsItem{
|
||||
Articul: "some-sku",
|
||||
Photo: "/photo/path.jpg",
|
||||
Name: "some-name",
|
||||
Description: "bad-desc",
|
||||
Category: "",
|
||||
Type: "some-type",
|
||||
Producer: "my-producer",
|
||||
Pack: 123,
|
||||
Step: 10,
|
||||
Price: 12.34,
|
||||
TariffPrice: 43.21,
|
||||
Cart: 1998,
|
||||
Stock: 444,
|
||||
}
|
||||
|
||||
data := fbs.MakeDomainGoodItemFinished(gooditem)
|
||||
datahexed := hex.EncodeToString(data)
|
||||
println(datahexed)
|
||||
|
||||
got, err := fbs.ParseGoodsItem(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing: %w", err)
|
||||
}
|
||||
|
||||
if got != gooditem {
|
||||
gotStr := fmt.Sprintf("%v", got)
|
||||
hasStr := fmt.Sprintf("%v", gooditem)
|
||||
println(gotStr, "\n", hasStr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
return app
|
||||
@ -142,6 +109,75 @@ func newImportCmd(ctx context.Context) cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func newImportFromFileCmd(ctx context.Context) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "fromfile",
|
||||
Usage: "imports from file into db",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "src",
|
||||
Value: "",
|
||||
Usage: "source of the data.",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: decorateAction(ctx, importFromFileAction),
|
||||
}
|
||||
}
|
||||
|
||||
func newExportCmd(ctx context.Context) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "export",
|
||||
Usage: "category for exporting stored data",
|
||||
Subcommands: cli.Commands{
|
||||
newExportYMLCatalogCmd(ctx),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newExportYMLCatalogCmd(ctx context.Context) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "yml_catalog",
|
||||
Usage: "export data into as yml_catalog in xml format",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "dst",
|
||||
Usage: "destination path",
|
||||
Required: true,
|
||||
Value: "yml_catalog.xml",
|
||||
TakesFile: true,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "limit",
|
||||
Usage: "limits output offers to required value",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "pretty",
|
||||
Usage: "prettify output",
|
||||
},
|
||||
},
|
||||
Action: decorateAction(ctx, exportYMLCatalogAction),
|
||||
}
|
||||
}
|
||||
|
||||
func newTestCmd(ctx context.Context) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "test",
|
||||
Usage: "various commands for testing",
|
||||
Subcommands: cli.Commands{
|
||||
newTestFBSCmd(ctx),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newTestFBSCmd(ctx context.Context) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "fbs",
|
||||
Usage: "serialize and deserialize gooditem entity",
|
||||
Action: decorateAction(ctx, testFBSAction),
|
||||
}
|
||||
}
|
||||
|
||||
func newViewCmd(ctx context.Context) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "view",
|
||||
@ -224,22 +260,6 @@ func newViewCategoriesListCmd(ctx context.Context) cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func newImportFromFileCmd(ctx context.Context) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "fromfile",
|
||||
Usage: "imports from file into db",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "src",
|
||||
Value: "",
|
||||
Usage: "source of the data.",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: decorateAction(ctx, importFromFileAction),
|
||||
}
|
||||
}
|
||||
|
||||
func viewItemsGetAction(ctx context.Context, c *cli.Context) error {
|
||||
r, err := components.GetRepository()
|
||||
if err != nil {
|
||||
@ -483,3 +503,151 @@ func decorateAction(ctx context.Context, a action) cli.ActionFunc {
|
||||
return a(ctx, c)
|
||||
}
|
||||
}
|
||||
|
||||
func exportYMLCatalogAction(ctx context.Context, c *cli.Context) error {
|
||||
path := c.String("dst")
|
||||
limit := c.Int("limit")
|
||||
pretty := c.Bool("pretty")
|
||||
|
||||
log, err := components.GetLogger()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting logger: %w", err)
|
||||
}
|
||||
|
||||
r, err := components.GetRepository()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting repository: %w", err)
|
||||
}
|
||||
|
||||
categories, err := r.Category().List(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("listing categories: %w", err)
|
||||
}
|
||||
|
||||
shop := export.Shop{
|
||||
Currencies: []export.Currency{{
|
||||
ID: "RUR",
|
||||
Rate: 1,
|
||||
}},
|
||||
Categories: make([]export.Category, 0, len(categories)),
|
||||
}
|
||||
|
||||
categoryByNameIdx := make(map[string]int64, len(categories))
|
||||
for _, category := range categories {
|
||||
categoryByNameIdx[category.Name] = category.ID
|
||||
shop.Categories = append(shop.Categories, export.Category{
|
||||
ID: category.ID,
|
||||
Name: category.Name,
|
||||
})
|
||||
}
|
||||
|
||||
itemsIter, err := r.GoodsItem().ListIter(ctx, 1)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting items iterator: %w", err)
|
||||
}
|
||||
|
||||
for item := range itemsIter {
|
||||
offer := goodsItemAsOffer(item, categoryByNameIdx)
|
||||
shop.Offers = append(shop.Offers, offer)
|
||||
}
|
||||
if err = ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating file: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
errClose := f.Close()
|
||||
if err == nil {
|
||||
err = errClose
|
||||
return
|
||||
}
|
||||
|
||||
log.Err(errClose).Msg("file closed or not")
|
||||
}()
|
||||
|
||||
if limit > 0 {
|
||||
shop.Offers = shop.Offers[:limit]
|
||||
}
|
||||
|
||||
container := export.YmlContainer{
|
||||
YmlCatalog: export.YmlCatalog{
|
||||
Shop: shop,
|
||||
Date: time.Now(),
|
||||
},
|
||||
}
|
||||
|
||||
_, err = f.Write([]byte(xml.Header))
|
||||
if err != nil {
|
||||
return fmt.Errorf("writing header: %w", err)
|
||||
}
|
||||
_, err = f.Write([]byte("<!DOCTYPE yml_catalog SYSTEM \"shops.dtd\">\n"))
|
||||
enc := xml.NewEncoder(f)
|
||||
if pretty {
|
||||
enc.Indent("", " ")
|
||||
}
|
||||
return enc.Encode(container)
|
||||
}
|
||||
|
||||
func goodsItemAsOffer(in entity.GoodsItem, categoryIDByName map[string]int64) (out export.Offer) {
|
||||
const defaultType = "vendor.model"
|
||||
const defaultCurrency = "RUR"
|
||||
const defaultAvailable = true
|
||||
const quantityParamName = "Количество на складе «Москва»"
|
||||
|
||||
categoryID := categoryIDByName[in.Type]
|
||||
|
||||
out = export.Offer{
|
||||
ID: in.Cart,
|
||||
Price: int(in.TariffPrice),
|
||||
CategoryID: categoryID,
|
||||
PictureURLs: []string{
|
||||
in.Photo,
|
||||
},
|
||||
|
||||
Model: in.Name,
|
||||
Vendor: in.Producer,
|
||||
TypePrefix: in.Name,
|
||||
Description: in.Description,
|
||||
ManufacturerWarrany: true,
|
||||
Params: []export.Param{
|
||||
{
|
||||
Name: quantityParamName,
|
||||
Value: strconv.Itoa(in.Stock),
|
||||
},
|
||||
},
|
||||
|
||||
Type: defaultType,
|
||||
CurrencyID: defaultCurrency,
|
||||
Available: defaultAvailable,
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func testFBSAction(ctx context.Context, c *cli.Context) error {
|
||||
var gooditem entity.GoodsItem
|
||||
err := gofakeit.Struct(&gooditem)
|
||||
if err != nil {
|
||||
return fmt.Errorf("faking struct: %w", err)
|
||||
}
|
||||
|
||||
data := fbs.MakeDomainGoodItemFinished(gooditem)
|
||||
datahexed := hex.EncodeToString(data)
|
||||
println(datahexed)
|
||||
|
||||
got, err := fbs.ParseGoodsItem(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing: %w", err)
|
||||
}
|
||||
|
||||
if got != gooditem {
|
||||
gotStr := fmt.Sprintf("%v", got)
|
||||
hasStr := fmt.Sprintf("%v", gooditem)
|
||||
println(gotStr, "\n", hasStr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user