天天看点

go-zero 实践 - 编写仓储、订单RPC\API服务(五)

作者:IT技术帮

按照前面的二、三、四章节,先创建RPC项目、再定义模型、然后编写RPC、API服务,就可以完成仓储、订单的RPC、API服务开发,其目录结构如下

go-zero-my
    |___systemmanage
    |___stockmanage
    |___ordermanage           

一、仓储模型

go-zero 实践 - 编写仓储、订单RPC\API服务(五)

1、产品模型

package schema

import (
	"entgo.io/ent"
	"entgo.io/ent/dialect"
	"entgo.io/ent/dialect/entsql"
	"entgo.io/ent/schema"
	"entgo.io/ent/schema/edge"
	"entgo.io/ent/schema/field"
	"go-zero-my/common/orm/ent/mixins"
)

type Product struct {
	ent.Schema
}

func (Product) Fields() []ent.Field {
	return []ent.Field{
		field.String("code").Comment("编码").Unique().
			SchemaType(map[string]string{
				dialect.MySQL: "varchar(32)",
			}),
		field.String("name").Comment("名称").Unique().
			SchemaType(map[string]string{
				dialect.MySQL: "varchar(32)",
			}),
		field.String("uom").Comment("单位").
			SchemaType(map[string]string{
				dialect.MySQL: "varchar(16)",
			}),
		field.Float("price").Comment("单价").
			SchemaType(map[string]string{
				dialect.MySQL: "decimal(6,2)",
			}),
	}
}

func (Product) Mixin() []ent.Mixin {
	return []ent.Mixin{
		mixins.BaseMixin{},
	}
}

func (Product) Edges() []ent.Edge {
	return []ent.Edge{
		edge.To("inventory", Inventory.Type),
		edge.To("transactiondetails", TransactionDetails.Type).StorageKey(edge.Column("product_id")), //另一种方法配置关系字段,在transactiondetails里不需要定义product_id字段
	}
}
func (Product) Annotations() []schema.Annotation {
	return []schema.Annotation{
		entsql.Annotation{Table: "wh_product"},
	}
}
           

2、仓库模型

package schema

import (
	"entgo.io/ent"
	"entgo.io/ent/dialect"
	"entgo.io/ent/dialect/entsql"
	"entgo.io/ent/schema"
	"entgo.io/ent/schema/edge"
	"entgo.io/ent/schema/field"
	"go-zero-my/common/orm/ent/mixins"
)

type Warehouse struct {
	ent.Schema
}

func (Warehouse) Fields() []ent.Field {
	return []ent.Field{
		field.String("name").Comment("名称").Unique().
			SchemaType(map[string]string{
				dialect.MySQL: "varchar(32)",
			}),
	}
}

func (Warehouse) Mixin() []ent.Mixin {
	return []ent.Mixin{
		mixins.BaseMixin{},
	}
}

func (Warehouse) Edges() []ent.Edge {
	return []ent.Edge{
		edge.To("inventory", Inventory.Type),
		edge.To("transactiondetails", TransactionDetails.Type).StorageKey(edge.Column("warehouse_id")), //另一种方法配置关系字段,在transactiondetails里不需要定义warehouse_id字段
	}
}
func (Warehouse) Annotations() []schema.Annotation {
	return []schema.Annotation{
		entsql.Annotation{Table: "wh_warehouse"},
	}
}
           

3、库存模型

package schema

import (
	"entgo.io/ent"
	"entgo.io/ent/dialect"
	"entgo.io/ent/dialect/entsql"
	"entgo.io/ent/schema"
	"entgo.io/ent/schema/edge"
	"entgo.io/ent/schema/field"
	"go-zero-my/common/orm/ent/mixins"
)

type Inventory struct {
	ent.Schema
}

func (Inventory) Fields() []ent.Field {
	return []ent.Field{
		field.Float("qty").Comment("数量").
			SchemaType(map[string]string{
				dialect.MySQL: "decimal(18,2)",
			}),
		field.Uint64("product_id").Comment("商品ID"),
		field.Uint64("warehouse_id").Comment("仓库ID"),
	}
}

func (Inventory) Mixin() []ent.Mixin {
	return []ent.Mixin{
		mixins.BaseMixin{},
	}
}

func (Inventory) Edges() []ent.Edge {
	return []ent.Edge{
		edge.From("product", Product.Type).Field("product_id").Ref("inventory").Unique().Required(),
		edge.From("warehouse", Warehouse.Type).Field("warehouse_id").Ref("inventory").Unique().Required(),
	}
}

func (Inventory) Indexes() []ent.Index {
	return []ent.Index{
		//index.Fields("product_id", "warehouse_id"), //按字段建立索引
		//index.Edges("warehouse", "product"), //按边建立索引
	}
}

func (Inventory) Annotations() []schema.Annotation {
	return []schema.Annotation{
		entsql.Annotation{Table: "wh_inventory"},
	}
}
           

4、库存交易明细

package schema

import (
	"entgo.io/ent"
	"entgo.io/ent/dialect"
	"entgo.io/ent/dialect/entsql"
	"entgo.io/ent/schema"
	"entgo.io/ent/schema/edge"
	"entgo.io/ent/schema/field"
	"go-zero-my/common/orm/ent/mixins"
	"time"
)

type TransactionDetails struct {
	ent.Schema
}

func (TransactionDetails) Fields() []ent.Field {
	return []ent.Field{
		field.String("number").Comment("单号").
			SchemaType(map[string]string{
				dialect.MySQL: "varchar(32)",
			}),
		field.Enum("bill_type").Comment("单据类型").
			Values("delivery", "scrap", "receipt"),
		field.Float("qty").Comment("数量").
			SchemaType(map[string]string{
				dialect.MySQL: "decimal(18,2)",
			}),
		field.Time("tran_time").
			Comment("交易时间").
			Default(time.Now),
	}
}

func (TransactionDetails) Mixin() []ent.Mixin {
	return []ent.Mixin{
		mixins.BaseMixin{},
	}
}

func (TransactionDetails) Edges() []ent.Edge {
	return []ent.Edge{
		edge.From("product", Product.Type).Ref("transactiondetails").Unique().Required(),
		edge.From("warehouse", Warehouse.Type).Ref("transactiondetails").Unique().Required(),
	}
}

func (TransactionDetails) Indexes() []ent.Index {
	return []ent.Index{}
}

func (TransactionDetails) Annotations() []schema.Annotation {
	return []schema.Annotation{
		entsql.Annotation{Table: "wh_transactiondetails"},
	}
}
           

二、订单模型

1、客户模型

package schema

import (
	"entgo.io/ent"
	"entgo.io/ent/dialect"
	"entgo.io/ent/dialect/entsql"
	"entgo.io/ent/schema"
	"entgo.io/ent/schema/edge"
	"entgo.io/ent/schema/field"
	"go-zero-my/common/orm/ent/mixins"
)

type Customer struct {
	ent.Schema
}

func (Customer) Fields() []ent.Field {
	return []ent.Field{
		field.String("name").Comment("名称").Unique().
			SchemaType(map[string]string{
				dialect.MySQL: "varchar(32)",
			}),
	}
}

func (Customer) Mixin() []ent.Mixin {
	return []ent.Mixin{
		mixins.BaseMixin{},
	}
}

func (Customer) Edges() []ent.Edge {
	return []ent.Edge{
		edge.To("order", Order.Type),
	}
}
func (Customer) Annotations() []schema.Annotation {
	return []schema.Annotation{
		entsql.Annotation{Table: "ord_customer"},
	}
}
           

2、订单模型

package schema

import (
	"entgo.io/ent"
	"entgo.io/ent/dialect"
	"entgo.io/ent/dialect/entsql"
	"entgo.io/ent/schema"
	"entgo.io/ent/schema/edge"
	"entgo.io/ent/schema/field"
	"go-zero-my/common/orm/ent/mixins"
	"time"
)

type Order struct {
	ent.Schema
}

func (Order) Fields() []ent.Field {
	return []ent.Field{
		field.Time("order_date").
			Comment("订单日期").
			Default(time.Now),
		field.String("order_no").Comment("订单编号").Unique().
			SchemaType(map[string]string{
				dialect.MySQL: "varchar(32)",
			}),
		field.Uint64("customer_id").Comment("客户ID"),
		field.String("remark").Comment("备注").Optional().
			SchemaType(map[string]string{
				dialect.MySQL: "varchar(200)",
			}),
	}
}

func (Order) Mixin() []ent.Mixin {
	return []ent.Mixin{
		mixins.BaseMixin{},
	}
}

func (Order) Edges() []ent.Edge {
	return []ent.Edge{
		edge.From("customer", Customer.Type).Field("customer_id").Ref("order").Unique().Required(),
		edge.To("orderitem", OrderItem.Type),
	}
}
func (Order) Annotations() []schema.Annotation {
	return []schema.Annotation{
		entsql.Annotation{Table: "ord_order"},
	}
}
           

3、订单明细模型

package schema

import (
	"entgo.io/ent"
	"entgo.io/ent/dialect"
	"entgo.io/ent/dialect/entsql"
	"entgo.io/ent/schema"
	"entgo.io/ent/schema/edge"
	"entgo.io/ent/schema/field"
	"entgo.io/ent/schema/index"
	"go-zero-my/common/orm/ent/mixins"
)

type OrderItem struct {
	ent.Schema
}

func (OrderItem) Fields() []ent.Field {
	return []ent.Field{
		field.Uint64("order_id").Comment("订单ID"),
		field.Uint64("product_id").Comment("商品ID"),
		field.Float("qty").Comment("数量").
			SchemaType(map[string]string{
				dialect.MySQL: "decimal(18,2)",
			}),
		field.Float("price").Comment("单价").
			SchemaType(map[string]string{
				dialect.MySQL: "decimal(6,2)",
			}),
	}
}

func (OrderItem) Mixin() []ent.Mixin {
	return []ent.Mixin{
		mixins.BaseMixin{},
	}
}

func (OrderItem) Edges() []ent.Edge {
	return []ent.Edge{
		edge.From("order", Order.Type).Field("order_id").Ref("orderitem").Unique().Required(),
	}
}

func (OrderItem) Indexes() []ent.Index {
	return []ent.Index{
		index.Fields("order_id", "product_id").Unique(), //按字段建立索引
	}
}

func (OrderItem) Annotations() []schema.Annotation {
	return []schema.Annotation{
		entsql.Annotation{Table: "ord_orderitem"},
	}
}
           

三、项目重构

将ent从rpc项目中提出来,将所有的模型放在一起,这样订单明细与产品就可以建关系

1、建立ent目录

在项目根目录(go-zero-my)下执行如下命令建立ent目录,注意,Example首字母要大写

go run -mod=mod entgo.io/ent/cmd/ent new Example           

建立后删除ent\schema下的 example.go文件

2、将三个RPC的模型复制到ent\schema目录

3、在订单明细、产品模型,增加边

func (OrderItem) Edges() []ent.Edge {
	return []ent.Edge{
		edge.From("order", Order.Type).Field("order_id").Ref("orderitem").Unique().Required(),
		edge.From("product", Product.Type).Field("product_id").Ref("orderitem").Unique().Required(),
	}
}           
func (Product) Edges() []ent.Edge {
	return []ent.Edge{
		edge.To("inventory", Inventory.Type),
		edge.To("transactiondetails", TransactionDetails.Type).StorageKey(edge.Column("product_id")), //另一种方法配置关系字段,在transactiondetails里不需要定义product_id字段
		edge.To("orderitem", OrderItem.Type),
	}
}           

4、产生ent代码

go run -mod=mod entgo.io/ent/cmd/ent generate ./ent/schema           

5、产生ent模板代码

将其中一个rpc\ent下的template复制到go-zero-my\ent目录,然后执行如下命令

go run -mod=mod entgo.io/ent/cmd/ent generate --template glob="./ent/template/*.tmpl" ./ent/schema           

6、删除各rpc下ent目录,然后修改相应文件的ent引用路径

7、将syndb.go移到根目录,删除各rpc下的syndb.go文件

修改import路径

go-zero 实践 - 编写仓储、订单RPC\API服务(五)

然后在根目录下(go-zero-my)执行数据库迁移 go run syndb.go

8、重构后目录结构如下

go-zero 实践 - 编写仓储、订单RPC\API服务(五)

9、生成proto文件和logic代码的命令变化

--schema参数改为根目录下的ent,命令执行目录还是在rpc目录下

goctls rpc ent --schema=../../ent/schema --service_name=order --project_name=order --model=Customer --group=customer --proto_out=./desc/customer.proto --style=gozero           

10、其他按照二、三、四章节完成服务的编写即可

继续阅读