feat: 初始化shop-crm-agent项目,实现基础CLI与CRM操作能力

本提交初始化完整的shop-crm-agent项目:
1. 创建基础项目结构与配置文件(.gitignore、go.mod/go.sum)
2. 添加项目许可协议与文档(README.md、AGENTS.md、SKILL.md)
3. 实现核心CLI入口与命令框架
4. 封装Protobuf API客户端与完整的命令实现
5. 添加单元测试覆盖核心功能与边界情况
6. 提供构建脚本与版本管理能力
This commit is contained in:
2026-08-01 01:36:37 +08:00
commit 3466e19d13
15 changed files with 8554 additions and 0 deletions
+568
View File
@@ -0,0 +1,568 @@
package command
import (
"errors"
dto "code.zhecent.com/open/shop-crm-agent/internal/api"
"github.com/spf13/cobra"
)
func newCrmAgentEditCmd() *cobra.Command {
cmd := &cobra.Command{Use: "edit", Short: "通过服务端会话编辑报价", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }}
cmd.AddCommand(newCrmAgentEditBeginCmd(), newCrmAgentEditPreviewCmd(), newCrmAgentEditCommitCmd(), newCrmAgentEditDiscardCmd(), newCrmAgentEditFloorCmd(), newCrmAgentEditSpaceCmd(), newCrmAgentEditCategoryCmd(), newCrmAgentEditLineCmd(), newCrmAgentEditFeeCmd(), newCrmAgentEditPricingCmd())
return cmd
}
func newCrmAgentEditBeginCmd() *cobra.Command {
var quotationID uint64
var write crmAgentWriteOptions
cmd := &cobra.Command{Use: "begin", Short: "开始报价编辑会话", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error {
client, err := newCrmAgentHTTPClient()
if err != nil {
return err
}
response, err := client.EditBegin(cmd.Context(), &dto.QuotationEditBeginRequest{Command: crmAgentCommandHeader(write), QuotationId: quotationID})
return printCrmAgentResult(response, err)
}}
cmd.Flags().Uint64Var(&quotationID, "quotation-id", 0, "报价 ID")
_ = cmd.MarkFlagRequired("quotation-id")
bindCrmAgentWrite(cmd, &write)
return cmd
}
func newCrmAgentEditPreviewCmd() *cobra.Command {
var sessionID string
cmd := &cobra.Command{Use: "preview", Short: "预览编辑并生成 changeSetId", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error {
client, err := newCrmAgentHTTPClient()
if err != nil {
return err
}
response, err := client.EditPreview(cmd.Context(), &dto.QuotationEditPreviewRequest{SessionId: sessionID})
return printCrmAgentResult(response, err)
}}
bindSessionID(cmd, &sessionID)
return cmd
}
func newCrmAgentEditCommitCmd() *cobra.Command {
var sessionID, changeSet string
var revision int32
var write crmAgentWriteOptions
cmd := &cobra.Command{Use: "commit", Short: "按 revision 和 changeSetId 提交编辑", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error {
client, err := newCrmAgentHTTPClient()
if err != nil {
return err
}
response, err := client.EditCommit(cmd.Context(), &dto.QuotationEditCommitRequest{Command: crmAgentCommandHeader(write), SessionId: sessionID, Revision: revision, ChangeSetId: changeSet})
return printCrmAgentResult(response, err)
}}
bindSessionID(cmd, &sessionID)
cmd.Flags().Int32Var(&revision, "revision", 0, "preview 返回的 revision")
cmd.Flags().StringVar(&changeSet, "change-set-id", "", "preview 返回的 changeSetId")
_ = cmd.MarkFlagRequired("revision")
_ = cmd.MarkFlagRequired("change-set-id")
bindCrmAgentWrite(cmd, &write)
return cmd
}
func newCrmAgentEditDiscardCmd() *cobra.Command {
var sessionID string
var write crmAgentWriteOptions
cmd := &cobra.Command{Use: "discard", Short: "丢弃编辑会话", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error {
client, err := newCrmAgentHTTPClient()
if err != nil {
return err
}
response, err := client.EditDiscard(cmd.Context(), &dto.QuotationEditDiscardRequest{Command: crmAgentCommandHeader(write), SessionId: sessionID})
return printCrmAgentResult(response, err)
}}
bindSessionID(cmd, &sessionID)
bindCrmAgentWrite(cmd, &write)
return cmd
}
func bindSessionID(cmd *cobra.Command, value *string) {
cmd.Flags().StringVar(value, "session-id", "", "报价编辑会话 ID")
_ = cmd.MarkFlagRequired("session-id")
}
func newCrmAgentEditMutationCmd(use, short string, bind func(*cobra.Command), build func() *dto.QuotationEditCommandRequest) *cobra.Command {
var sessionID string
var write crmAgentWriteOptions
cmd := &cobra.Command{Use: use, Short: short, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error {
request := build()
if request == nil {
return errors.New("编辑命令构造失败")
}
request.Command, request.SessionId = crmAgentCommandHeader(write), sessionID
client, err := newCrmAgentHTTPClient()
if err != nil {
return err
}
response, err := client.EditCommand(cmd.Context(), request)
return printCrmAgentResult(response, err)
}}
bindSessionID(cmd, &sessionID)
bindCrmAgentWrite(cmd, &write)
if bind != nil {
bind(cmd)
}
return cmd
}
func newCrmAgentEditFloorCmd() *cobra.Command {
cmd := &cobra.Command{Use: "floor", Short: "增改排序和移除楼层", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }}
cmd.AddCommand(newCrmAgentFloorAddCmd(), newCrmAgentFloorRenameCmd(), newCrmAgentFloorReorderCmd(), newCrmAgentFloorRemoveCmd())
return cmd
}
func newCrmAgentFloorAddCmd() *cobra.Command {
var id, name string
var index int32 = -1
return newCrmAgentEditMutationCmd("add", "添加楼层", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "id", "", "可选稳定楼层 ID")
cmd.Flags().StringVar(&name, "name", "", "楼层名称")
cmd.Flags().Int32Var(&index, "index", -1, "插入索引,-1追加")
_ = cmd.MarkFlagRequired("name")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_AddFloor{AddFloor: &dto.AddFloor{Id: id, Name: name, Index: index}}}
})
}
func newCrmAgentFloorRenameCmd() *cobra.Command {
var id, name string
return newCrmAgentEditMutationCmd("rename", "重命名楼层", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "floor-id", "", "楼层 ID")
cmd.Flags().StringVar(&name, "name", "", "新名称")
_ = cmd.MarkFlagRequired("floor-id")
_ = cmd.MarkFlagRequired("name")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_RenameFloor{RenameFloor: &dto.RenameFloor{FloorId: id, Name: name}}}
})
}
func newCrmAgentFloorReorderCmd() *cobra.Command {
var id string
var index int32
return newCrmAgentEditMutationCmd("reorder", "调整楼层顺序", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "floor-id", "", "楼层 ID")
cmd.Flags().Int32Var(&index, "index", 0, "目标索引")
_ = cmd.MarkFlagRequired("floor-id")
_ = cmd.MarkFlagRequired("index")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_ReorderFloor{ReorderFloor: &dto.ReorderFloor{FloorId: id, Index: index}}}
})
}
func newCrmAgentFloorRemoveCmd() *cobra.Command {
var id string
var cascade bool
return newCrmAgentEditMutationCmd("remove", "移除楼层", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "floor-id", "", "楼层 ID")
cmd.Flags().BoolVar(&cascade, "cascade", false, "同时移除下属空间、分类和产品行")
_ = cmd.MarkFlagRequired("floor-id")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_RemoveFloor{RemoveFloor: &dto.RemoveFloor{FloorId: id, Cascade: cascade}}}
})
}
func newCrmAgentEditSpaceCmd() *cobra.Command {
cmd := &cobra.Command{Use: "space", Short: "增改移动排序和移除空间", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }}
cmd.AddCommand(newCrmAgentSpaceAddCmd(), newCrmAgentSpaceRenameCmd(), newCrmAgentSpaceMoveCmd(), newCrmAgentSpaceReorderCmd(), newCrmAgentSpaceRemoveCmd())
return cmd
}
func newCrmAgentSpaceAddCmd() *cobra.Command {
var id, floorID, name string
var index int32 = -1
return newCrmAgentEditMutationCmd("add", "添加空间", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "id", "", "可选稳定空间 ID")
cmd.Flags().StringVar(&floorID, "floor-id", "", "楼层 ID")
cmd.Flags().StringVar(&name, "name", "", "空间名称")
cmd.Flags().Int32Var(&index, "index", -1, "插入索引")
_ = cmd.MarkFlagRequired("floor-id")
_ = cmd.MarkFlagRequired("name")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_AddSpace{AddSpace: &dto.AddSpace{Id: id, FloorId: floorID, Name: name, Index: index}}}
})
}
func newCrmAgentSpaceRenameCmd() *cobra.Command {
var id, name string
return newCrmAgentEditMutationCmd("rename", "重命名空间", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "space-id", "", "空间 ID")
cmd.Flags().StringVar(&name, "name", "", "新名称")
_ = cmd.MarkFlagRequired("space-id")
_ = cmd.MarkFlagRequired("name")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_RenameSpace{RenameSpace: &dto.RenameSpace{SpaceId: id, Name: name}}}
})
}
func newCrmAgentSpaceMoveCmd() *cobra.Command {
var id, floorID string
var index int32 = -1
return newCrmAgentEditMutationCmd("move", "移动空间到其他楼层", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "space-id", "", "空间 ID")
cmd.Flags().StringVar(&floorID, "target-floor-id", "", "目标楼层 ID")
cmd.Flags().Int32Var(&index, "index", -1, "目标索引")
_ = cmd.MarkFlagRequired("space-id")
_ = cmd.MarkFlagRequired("target-floor-id")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_MoveSpace{MoveSpace: &dto.MoveSpace{SpaceId: id, TargetFloorId: floorID, Index: index}}}
})
}
func newCrmAgentSpaceReorderCmd() *cobra.Command {
var id string
var index int32
return newCrmAgentEditMutationCmd("reorder", "调整空间顺序", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "space-id", "", "空间 ID")
cmd.Flags().Int32Var(&index, "index", 0, "目标索引")
_ = cmd.MarkFlagRequired("space-id")
_ = cmd.MarkFlagRequired("index")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_ReorderSpace{ReorderSpace: &dto.ReorderSpace{SpaceId: id, Index: index}}}
})
}
func newCrmAgentSpaceRemoveCmd() *cobra.Command {
var id string
var cascade bool
return newCrmAgentEditMutationCmd("remove", "移除空间", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "space-id", "", "空间 ID")
cmd.Flags().BoolVar(&cascade, "cascade", false, "同时移除分类和产品行")
_ = cmd.MarkFlagRequired("space-id")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_RemoveSpace{RemoveSpace: &dto.RemoveSpace{SpaceId: id, Cascade: cascade}}}
})
}
func newCrmAgentEditCategoryCmd() *cobra.Command {
cmd := &cobra.Command{Use: "category", Short: "增改排序和移除分类", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }}
cmd.AddCommand(newCrmAgentCategoryAddCmd(), newCrmAgentCategoryRenameCmd(), newCrmAgentCategoryReorderCmd(), newCrmAgentCategoryRemoveCmd())
return cmd
}
func newCrmAgentCategoryAddCmd() *cobra.Command {
var id, floorID, spaceID, name, source, sourceKey string
var index int32 = -1
return newCrmAgentEditMutationCmd("add", "添加分类", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "id", "", "可选稳定分类 ID")
cmd.Flags().StringVar(&floorID, "floor-id", "", "楼层 ID")
cmd.Flags().StringVar(&spaceID, "space-id", "", "空间 ID")
cmd.Flags().StringVar(&name, "name", "", "分类名称")
cmd.Flags().StringVar(&source, "source", "custom", "来源")
cmd.Flags().StringVar(&sourceKey, "source-key", "", "来源 key")
cmd.Flags().Int32Var(&index, "index", -1, "插入索引")
_ = cmd.MarkFlagRequired("floor-id")
_ = cmd.MarkFlagRequired("space-id")
_ = cmd.MarkFlagRequired("name")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_AddCategory{AddCategory: &dto.AddCategory{Id: id, FloorId: floorID, SpaceId: spaceID, Name: name, Source: source, SourceKey: sourceKey, Index: index}}}
})
}
func newCrmAgentCategoryRenameCmd() *cobra.Command {
var id, name string
return newCrmAgentEditMutationCmd("rename", "重命名分类", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "category-id", "", "分类 ID")
cmd.Flags().StringVar(&name, "name", "", "新名称")
_ = cmd.MarkFlagRequired("category-id")
_ = cmd.MarkFlagRequired("name")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_RenameCategory{RenameCategory: &dto.RenameCategory{CategoryId: id, Name: name}}}
})
}
func newCrmAgentCategoryReorderCmd() *cobra.Command {
var id string
var index int32
return newCrmAgentEditMutationCmd("reorder", "调整分类顺序", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "category-id", "", "分类 ID")
cmd.Flags().Int32Var(&index, "index", 0, "目标索引")
_ = cmd.MarkFlagRequired("category-id")
_ = cmd.MarkFlagRequired("index")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_ReorderCategory{ReorderCategory: &dto.ReorderCategory{CategoryId: id, Index: index}}}
})
}
func newCrmAgentCategoryRemoveCmd() *cobra.Command {
var id string
var cascade bool
return newCrmAgentEditMutationCmd("remove", "移除分类", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&id, "category-id", "", "分类 ID")
cmd.Flags().BoolVar(&cascade, "cascade", false, "同时移除产品行")
_ = cmd.MarkFlagRequired("category-id")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_RemoveCategory{RemoveCategory: &dto.RemoveCategory{CategoryId: id, Cascade: cascade}}}
})
}
func newCrmAgentEditLineCmd() *cobra.Command {
cmd := &cobra.Command{Use: "line", Short: "增改移动排序启停和移除产品行", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }}
cmd.AddCommand(newCrmAgentLineAddCatalogCmd(), newCrmAgentLineAddCustomCmd(), newCrmAgentLineUpdateCmd(), newCrmAgentLineMoveCmd(), newCrmAgentLineReorderCmd(), newCrmAgentLineActiveCmd(true), newCrmAgentLineActiveCmd(false), newCrmAgentLineRemoveCmd())
return cmd
}
type crmAgentLineTarget struct {
floorID, spaceID, categoryID string
index int32
}
func bindLineTarget(cmd *cobra.Command, target *crmAgentLineTarget) {
cmd.Flags().StringVar(&target.floorID, "floor-id", "", "楼层 ID")
cmd.Flags().StringVar(&target.spaceID, "space-id", "", "空间 ID")
cmd.Flags().StringVar(&target.categoryID, "category-id", "", "分类 ID")
cmd.Flags().Int32Var(&target.index, "index", -1, "分类内索引,-1追加")
_ = cmd.MarkFlagRequired("floor-id")
_ = cmd.MarkFlagRequired("space-id")
_ = cmd.MarkFlagRequired("category-id")
}
func newCrmAgentLineAddCatalogCmd() *cobra.Command {
var target crmAgentLineTarget
var skuID uint64
var quantity float64 = 1
var discountRate int32 = 100
var discountAmount int64
var remark string
return newCrmAgentEditMutationCmd("add-catalog", "按 SKU 添加产品库行", func(cmd *cobra.Command) {
bindLineTarget(cmd, &target)
cmd.Flags().Uint64Var(&skuID, "sku-id", 0, "产品库 SKU ID")
cmd.Flags().Float64Var(&quantity, "quantity", 1, "数量")
cmd.Flags().Int32Var(&discountRate, "discount-rate", 100, "折扣率0-100")
cmd.Flags().Int64Var(&discountAmount, "discount-amount", 0, "优惠金额(分)")
cmd.Flags().StringVar(&remark, "remark", "", "备注")
_ = cmd.MarkFlagRequired("sku-id")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_AddCatalogLine{AddCatalogLine: &dto.AddCatalogLine{FloorId: target.floorID, SpaceId: target.spaceID, CategoryId: target.categoryID, SkuId: skuID, Quantity: quantity, DiscountRate: discountRate, DiscountAmount: discountAmount, Remark: remark, Index: target.index}}}
})
}
func newCrmAgentLineAddCustomCmd() *cobra.Command {
var target crmAgentLineTarget
var name, spec, remark string
var quantity float64 = 1
var unitPrice, costPrice, discountAmount int64
var discountRate int32 = 100
return newCrmAgentEditMutationCmd("add-custom", "添加自定义产品行", func(cmd *cobra.Command) {
bindLineTarget(cmd, &target)
cmd.Flags().StringVar(&name, "name", "", "产品名称")
cmd.Flags().StringVar(&spec, "spec", "", "规格")
cmd.Flags().Float64Var(&quantity, "quantity", 1, "数量")
cmd.Flags().Int64Var(&unitPrice, "unit-price", 0, "售价(分)")
cmd.Flags().Int64Var(&costPrice, "cost-price", 0, "成本(分)")
cmd.Flags().Int32Var(&discountRate, "discount-rate", 100, "折扣率0-100")
cmd.Flags().Int64Var(&discountAmount, "discount-amount", 0, "优惠金额(分)")
cmd.Flags().StringVar(&remark, "remark", "", "备注")
_ = cmd.MarkFlagRequired("name")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_AddCustomLine{AddCustomLine: &dto.AddCustomLine{FloorId: target.floorID, SpaceId: target.spaceID, CategoryId: target.categoryID, GoodsName: name, SpecCombination: spec, Quantity: quantity, UnitPrice: unitPrice, CostPrice: costPrice, DiscountRate: discountRate, DiscountAmount: discountAmount, Remark: remark, Index: target.index}}}
})
}
func newCrmAgentLineUpdateCmd() *cobra.Command {
var sessionID, lineID, name, spec, remark string
var quantity float64
var unitPrice, costPrice, discountAmount int64
var discountRate int32
var write crmAgentWriteOptions
cmd := &cobra.Command{Use: "update", Short: "按已提供 flags 更新产品行", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error {
update := &dto.UpdateLine{LineId: lineID}
if cmd.Flags().Changed("name") {
update.GoodsName = &name
}
if cmd.Flags().Changed("spec") {
update.SpecCombination = &spec
}
if cmd.Flags().Changed("quantity") {
update.Quantity = &quantity
}
if cmd.Flags().Changed("unit-price") {
update.UnitPrice = &unitPrice
}
if cmd.Flags().Changed("cost-price") {
update.CostPrice = &costPrice
}
if cmd.Flags().Changed("discount-rate") {
update.DiscountRate = &discountRate
}
if cmd.Flags().Changed("discount-amount") {
update.DiscountAmount = &discountAmount
}
if cmd.Flags().Changed("remark") {
update.Remark = &remark
}
client, err := newCrmAgentHTTPClient()
if err != nil {
return err
}
response, err := client.EditCommand(cmd.Context(), &dto.QuotationEditCommandRequest{Command: crmAgentCommandHeader(write), SessionId: sessionID, Edit: &dto.QuotationEditCommandRequest_UpdateLine{UpdateLine: update}})
return printCrmAgentResult(response, err)
}}
bindSessionID(cmd, &sessionID)
bindCrmAgentWrite(cmd, &write)
cmd.Flags().StringVar(&lineID, "line-id", "", "产品行 ID")
cmd.Flags().StringVar(&name, "name", "", "产品名称(仅自定义行)")
cmd.Flags().StringVar(&spec, "spec", "", "规格(仅自定义行)")
cmd.Flags().Float64Var(&quantity, "quantity", 0, "数量")
cmd.Flags().Int64Var(&unitPrice, "unit-price", 0, "售价(分)")
cmd.Flags().Int64Var(&costPrice, "cost-price", 0, "成本(分,仅自定义行)")
cmd.Flags().Int32Var(&discountRate, "discount-rate", 0, "折扣率0-100")
cmd.Flags().Int64Var(&discountAmount, "discount-amount", 0, "优惠金额(分)")
cmd.Flags().StringVar(&remark, "remark", "", "备注")
_ = cmd.MarkFlagRequired("line-id")
return cmd
}
func newCrmAgentLineMoveCmd() *cobra.Command {
var target crmAgentLineTarget
var lineID string
return newCrmAgentEditMutationCmd("move", "移动产品行", func(cmd *cobra.Command) {
bindLineTarget(cmd, &target)
cmd.Flags().StringVar(&lineID, "line-id", "", "产品行 ID")
_ = cmd.MarkFlagRequired("line-id")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_MoveLine{MoveLine: &dto.MoveLine{LineId: lineID, FloorId: target.floorID, SpaceId: target.spaceID, CategoryId: target.categoryID, Index: target.index}}}
})
}
func newCrmAgentLineReorderCmd() *cobra.Command {
var lineID string
var index int32
return newCrmAgentEditMutationCmd("reorder", "调整产品行在分类内的顺序", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&lineID, "line-id", "", "产品行 ID")
cmd.Flags().Int32Var(&index, "index", 0, "目标索引")
_ = cmd.MarkFlagRequired("line-id")
_ = cmd.MarkFlagRequired("index")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_ReorderLine{ReorderLine: &dto.ReorderLine{LineId: lineID, Index: index}}}
})
}
func newCrmAgentLineActiveCmd(active bool) *cobra.Command {
use, short := "disable", "停用产品行"
if active {
use, short = "enable", "启用产品行"
}
var lineID string
return newCrmAgentEditMutationCmd(use, short, func(cmd *cobra.Command) {
cmd.Flags().StringVar(&lineID, "line-id", "", "产品行 ID")
_ = cmd.MarkFlagRequired("line-id")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_SetLineActive{SetLineActive: &dto.SetLineActive{LineId: lineID, Active: active}}}
})
}
func newCrmAgentLineRemoveCmd() *cobra.Command {
var lineID string
return newCrmAgentEditMutationCmd("remove", "移除产品行", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&lineID, "line-id", "", "产品行 ID")
_ = cmd.MarkFlagRequired("line-id")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_RemoveLine{RemoveLine: &dto.RemoveLine{LineId: lineID}}}
})
}
func newCrmAgentEditFeeCmd() *cobra.Command {
cmd := &cobra.Command{Use: "fee", Short: "增改排序和移除费用", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }}
cmd.AddCommand(newCrmAgentFeeAddCmd(), newCrmAgentFeeUpdateCmd(), newCrmAgentFeeReorderCmd(), newCrmAgentFeeRemoveCmd())
return cmd
}
func newCrmAgentFeeAddCmd() *cobra.Command {
var name, feeType, remark string
var fixedAmount int64
var percentage, index int32
index = -1
return newCrmAgentEditMutationCmd("add", "添加费用", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&name, "name", "", "费用名称")
cmd.Flags().StringVar(&feeType, "type", "fixed", "fixed/discounted_percent/original_percent")
cmd.Flags().Int64Var(&fixedAmount, "fixed-amount", 0, "固定金额(分)")
cmd.Flags().Int32Var(&percentage, "percentage", 0, "百分比0-100")
cmd.Flags().Int32Var(&index, "index", -1, "插入索引")
cmd.Flags().StringVar(&remark, "remark", "", "备注")
_ = cmd.MarkFlagRequired("name")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_AddFee{AddFee: &dto.AddFee{Name: name, Type: feeType, FixedAmount: fixedAmount, Percentage: percentage, Index: index, Remark: remark}}}
})
}
func newCrmAgentFeeUpdateCmd() *cobra.Command {
var sessionID, name, feeType, remark string
var index, percentage int32
var fixedAmount int64
var write crmAgentWriteOptions
cmd := &cobra.Command{Use: "update", Short: "按已提供 flags 更新费用", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error {
update := &dto.UpdateFee{Index: index}
if cmd.Flags().Changed("name") {
update.Name = &name
}
if cmd.Flags().Changed("type") {
update.Type = &feeType
}
if cmd.Flags().Changed("fixed-amount") {
update.FixedAmount = &fixedAmount
}
if cmd.Flags().Changed("percentage") {
update.Percentage = &percentage
}
if cmd.Flags().Changed("remark") {
update.Remark = &remark
}
client, err := newCrmAgentHTTPClient()
if err != nil {
return err
}
response, err := client.EditCommand(cmd.Context(), &dto.QuotationEditCommandRequest{Command: crmAgentCommandHeader(write), SessionId: sessionID, Edit: &dto.QuotationEditCommandRequest_UpdateFee{UpdateFee: update}})
return printCrmAgentResult(response, err)
}}
bindSessionID(cmd, &sessionID)
bindCrmAgentWrite(cmd, &write)
cmd.Flags().Int32Var(&index, "index", -1, "费用索引")
cmd.Flags().StringVar(&name, "name", "", "名称")
cmd.Flags().StringVar(&feeType, "type", "", "费用类型")
cmd.Flags().Int64Var(&fixedAmount, "fixed-amount", 0, "固定金额(分)")
cmd.Flags().Int32Var(&percentage, "percentage", 0, "百分比0-100")
cmd.Flags().StringVar(&remark, "remark", "", "备注")
_ = cmd.MarkFlagRequired("index")
return cmd
}
func newCrmAgentFeeReorderCmd() *cobra.Command {
var index, target int32
return newCrmAgentEditMutationCmd("reorder", "调整费用顺序", func(cmd *cobra.Command) {
cmd.Flags().Int32Var(&index, "index", -1, "当前索引")
cmd.Flags().Int32Var(&target, "target-index", 0, "目标索引")
_ = cmd.MarkFlagRequired("index")
_ = cmd.MarkFlagRequired("target-index")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_ReorderFee{ReorderFee: &dto.ReorderFee{Index: index, TargetIndex: target}}}
})
}
func newCrmAgentFeeRemoveCmd() *cobra.Command {
var index int32
return newCrmAgentEditMutationCmd("remove", "移除费用", func(cmd *cobra.Command) {
cmd.Flags().Int32Var(&index, "index", -1, "费用索引")
_ = cmd.MarkFlagRequired("index")
}, func() *dto.QuotationEditCommandRequest {
return &dto.QuotationEditCommandRequest{Edit: &dto.QuotationEditCommandRequest_RemoveFee{RemoveFee: &dto.RemoveFee{Index: index}}}
})
}
func newCrmAgentEditPricingCmd() *cobra.Command {
var sessionID, remark string
var discountRate int32
var discountAmount, actualAmount int64
var adjusted bool
var write crmAgentWriteOptions
cmd := &cobra.Command{Use: "pricing", Short: "修改整单折扣、优惠、实际金额或调价标记", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error {
pricing := &dto.SetPricing{}
if cmd.Flags().Changed("discount-rate") {
pricing.DiscountRate = &discountRate
}
if cmd.Flags().Changed("discount-amount") {
pricing.DiscountAmount = &discountAmount
}
if cmd.Flags().Changed("actual-amount") {
pricing.ActualAmount = &actualAmount
}
if cmd.Flags().Changed("adjusted") {
pricing.HasPriceAdjustment = &adjusted
}
if cmd.Flags().Changed("remark") {
pricing.Remark = &remark
}
client, err := newCrmAgentHTTPClient()
if err != nil {
return err
}
response, err := client.EditCommand(cmd.Context(), &dto.QuotationEditCommandRequest{Command: crmAgentCommandHeader(write), SessionId: sessionID, Edit: &dto.QuotationEditCommandRequest_SetPricing{SetPricing: pricing}})
return printCrmAgentResult(response, err)
}}
bindSessionID(cmd, &sessionID)
bindCrmAgentWrite(cmd, &write)
cmd.Flags().Int32Var(&discountRate, "discount-rate", 0, "整单折扣率0-100")
cmd.Flags().Int64Var(&discountAmount, "discount-amount", 0, "整单优惠金额(分)")
cmd.Flags().Int64Var(&actualAmount, "actual-amount", 0, "实际成交金额(分)")
cmd.Flags().BoolVar(&adjusted, "adjusted", false, "是否标记人工调价")
cmd.Flags().StringVar(&remark, "remark", "", "报价备注")
return cmd
}