Ver Fonte

数据中心rpc开发

songxiaohang há 1 ano atrás
pai
commit
7d76180c03

+ 41 - 0
app/cmd/organization/internal/logic/getworkingchestbycodelogic.go

@@ -0,0 +1,41 @@
+package logic
+
+import (
+	"GtDataStore/app/model"
+	"context"
+	"github.com/jinzhu/copier"
+
+	"GtDataStore/app/cmd/organization/internal/svc"
+	"GtDataStore/app/cmd/organization/pb"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetWorkingChestByCodeLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetWorkingChestByCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWorkingChestByCodeLogic {
+	return &GetWorkingChestByCodeLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetWorkingChestByCodeLogic) GetWorkingChestByCode(in *pb.DcWorkingReq) (*pb.WorkingChest, error) {
+	//基础条件
+	workingChestInfo, err := l.svcCtx.WorkingChest.FindOneByCode(l.ctx, in.ProjectId, in.DeviceCode)
+	if err != nil && err != model.ErrNotFound {
+		logx.Errorf("not found workingUf data")
+		return nil, err
+	}
+
+	resp := &pb.WorkingChest{}
+	_ = copier.Copy(resp, workingChestInfo)
+	resp.CTime = workingChestInfo.CTime.Format("2006-01-02 15:04:05")
+
+	return resp, nil
+}

+ 41 - 0
app/cmd/organization/internal/logic/getworkingpumpbycodelogic.go

@@ -0,0 +1,41 @@
+package logic
+
+import (
+	"GtDataStore/app/model"
+	"context"
+	"github.com/jinzhu/copier"
+
+	"GtDataStore/app/cmd/organization/internal/svc"
+	"GtDataStore/app/cmd/organization/pb"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetWorkingPumpByCodeLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetWorkingPumpByCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWorkingPumpByCodeLogic {
+	return &GetWorkingPumpByCodeLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetWorkingPumpByCodeLogic) GetWorkingPumpByCode(in *pb.DcWorkingReq) (*pb.WorkingPump, error) {
+	//基础条件
+	workingPumpInfo, err := l.svcCtx.WorkingPump.FindOneByCode(l.ctx, in.ProjectId, in.DeviceCode)
+	if err != nil && err != model.ErrNotFound {
+		logx.Errorf("not found workingUf data")
+		return nil, err
+	}
+
+	resp := &pb.WorkingPump{}
+	_ = copier.Copy(resp, workingPumpInfo)
+	resp.CTime = workingPumpInfo.CTime.Format("2006-01-02 15:04:05")
+
+	return resp, nil
+}

+ 41 - 0
app/cmd/organization/internal/logic/getworkingrobycodelogic.go

@@ -0,0 +1,41 @@
+package logic
+
+import (
+	"GtDataStore/app/model"
+	"context"
+	"github.com/jinzhu/copier"
+
+	"GtDataStore/app/cmd/organization/internal/svc"
+	"GtDataStore/app/cmd/organization/pb"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetWorkingRoByCodeLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetWorkingRoByCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWorkingRoByCodeLogic {
+	return &GetWorkingRoByCodeLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetWorkingRoByCodeLogic) GetWorkingRoByCode(in *pb.DcWorkingReq) (*pb.WorkingRo, error) {
+	//基础条件
+	workingRoInfo, err := l.svcCtx.WorkingRo.FindOneByCode(l.ctx, in.ProjectId, in.DeviceCode)
+	if err != nil && err != model.ErrNotFound {
+		logx.Errorf("not found workingUf data")
+		return nil, err
+	}
+
+	resp := &pb.WorkingRo{}
+	_ = copier.Copy(resp, workingRoInfo)
+	resp.CTime = workingRoInfo.CTime.Format("2006-01-02 15:04:05")
+
+	return resp, nil
+}

+ 40 - 0
app/cmd/organization/internal/logic/getworkingufbycodelogic.go

@@ -0,0 +1,40 @@
+package logic
+
+import (
+	"GtDataStore/app/cmd/organization/internal/svc"
+	"GtDataStore/app/cmd/organization/pb"
+	"GtDataStore/app/model"
+	"context"
+	"github.com/jinzhu/copier"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetWorkingUfByCodeLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetWorkingUfByCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWorkingUfByCodeLogic {
+	return &GetWorkingUfByCodeLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetWorkingUfByCodeLogic) GetWorkingUfByCode(in *pb.DcWorkingReq) (*pb.WorkingUf, error) {
+	//基础条件
+	workingUfInfo, err := l.svcCtx.WorkingUf.FindOneByCode(l.ctx, in.ProjectId, in.DeviceCode)
+	if err != nil && err != model.ErrNotFound {
+		logx.Errorf("not found workingUf data")
+		return nil, err
+	}
+
+	resp := &pb.WorkingUf{}
+	_ = copier.Copy(resp, workingUfInfo)
+	resp.CTime = workingUfInfo.CTime.Format("2006-01-02 15:04:05")
+
+	return resp, nil
+}

+ 41 - 0
app/cmd/organization/internal/logic/getworkingvaluebycodelogic.go

@@ -0,0 +1,41 @@
+package logic
+
+import (
+	"GtDataStore/app/model"
+	"context"
+	"github.com/jinzhu/copier"
+
+	"GtDataStore/app/cmd/organization/internal/svc"
+	"GtDataStore/app/cmd/organization/pb"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetWorkingValueByCodeLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetWorkingValueByCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWorkingValueByCodeLogic {
+	return &GetWorkingValueByCodeLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *GetWorkingValueByCodeLogic) GetWorkingValueByCode(in *pb.DcWorkingReq) (*pb.WorkingValve, error) {
+	//基础条件
+	workingValveInfo, err := l.svcCtx.WorkingValve.FindOneByCode(l.ctx, in.ProjectId, in.DeviceCode)
+	if err != nil && err != model.ErrNotFound {
+		logx.Errorf("not found workingUf data")
+		return nil, err
+	}
+
+	resp := &pb.WorkingValve{}
+	_ = copier.Copy(resp, workingValveInfo)
+	resp.CTime = workingValveInfo.CTime.Format("2006-01-02 15:04:05")
+
+	return resp, nil
+}

+ 28 - 0
app/cmd/organization/internal/server/organizationServer.go

@@ -4,6 +4,9 @@
 package server
 
 import (
+	"context"
+
+	"GtDataStore/app/cmd/organization/internal/logic"
 	"GtDataStore/app/cmd/organization/internal/svc"
 	"GtDataStore/app/cmd/organization/pb"
 )
@@ -18,3 +21,28 @@ func NewOrganizationServer(svcCtx *svc.ServiceContext) *OrganizationServer {
 		svcCtx: svcCtx,
 	}
 }
+
+func (s *OrganizationServer) GetWorkingUfByCode(ctx context.Context, in *pb.DcWorkingReq) (*pb.WorkingUf, error) {
+	l := logic.NewGetWorkingUfByCodeLogic(ctx, s.svcCtx)
+	return l.GetWorkingUfByCode(in)
+}
+
+func (s *OrganizationServer) GetWorkingRoByCode(ctx context.Context, in *pb.DcWorkingReq) (*pb.WorkingRo, error) {
+	l := logic.NewGetWorkingRoByCodeLogic(ctx, s.svcCtx)
+	return l.GetWorkingRoByCode(in)
+}
+
+func (s *OrganizationServer) GetWorkingChestByCode(ctx context.Context, in *pb.DcWorkingReq) (*pb.WorkingChest, error) {
+	l := logic.NewGetWorkingChestByCodeLogic(ctx, s.svcCtx)
+	return l.GetWorkingChestByCode(in)
+}
+
+func (s *OrganizationServer) GetWorkingPumpByCode(ctx context.Context, in *pb.DcWorkingReq) (*pb.WorkingPump, error) {
+	l := logic.NewGetWorkingPumpByCodeLogic(ctx, s.svcCtx)
+	return l.GetWorkingPumpByCode(in)
+}
+
+func (s *OrganizationServer) GetWorkingValueByCode(ctx context.Context, in *pb.DcWorkingReq) (*pb.WorkingValve, error) {
+	l := logic.NewGetWorkingValueByCodeLogic(ctx, s.svcCtx)
+	return l.GetWorkingValueByCode(in)
+}

+ 12 - 15
app/cmd/organization/organization.go

@@ -2,8 +2,6 @@ package main
 
 import (
 	"GtDataStore/app/cmd/organization/internal/config"
-	"GtDataStore/app/cmd/organization/internal/logic/handler"
-	"GtDataStore/app/cmd/organization/internal/logic/job"
 	"GtDataStore/app/cmd/organization/internal/server"
 	"GtDataStore/app/cmd/organization/pb"
 	"github.com/zeromicro/go-zero/core/service"
@@ -13,8 +11,7 @@ import (
 
 	//"GtDataStore/app/cmd/organization/internal/server"
 	"GtDataStore/app/cmd/organization/internal/svc"
-	//"GtDataStore/app/cmd/organization/pb"
-	"GtDataStore/common/envitem"
+
 	"flag"
 	"fmt"
 
@@ -43,17 +40,17 @@ func main() {
 	})
 	defer s.Stop()
 
-	if c.Mode != "dev" {
-		envitem.SetOptions(envitem.Options{GtServerIp: c.GtServerIp})
-
-		go func() {
-			defer func() {
-				fmt.Print("async organization job stop.....\n")
-			}()
-			j := job.NewJob(1, "organization", ctx, handler.DeviceHandlerTable, handler.DeviceIntervalTable)
-			j.Run()
-		}()
-	}
+	//if c.Mode != "dev" {
+	//	envitem.SetOptions(envitem.Options{GtServerIp: c.GtServerIp})
+	//
+	//	go func() {
+	//		defer func() {
+	//			fmt.Print("async organization job stop.....\n")
+	//		}()
+	//		j := job.NewJob(1, "organization", ctx, handler.DeviceHandlerTable, handler.DeviceIntervalTable)
+	//		j.Run()
+	//	}()
+	//}
 
 	fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
 	s.Start()

+ 132 - 1
app/cmd/organization/organization.proto

@@ -3,7 +3,138 @@ syntax = "proto3";
 package pb;
 option go_package = "./pb";
 
+message DcWorkingReq{
+  int64   project_id = 1;
+  string  device_code = 2;
+}
 
-service Organization {
+message WorkingUf{
+  int64         id = 1;
+  int64         project_id = 2;
+  string        device_code = 3;
+  double        water_temperature = 4;  // 水温 摄氏度
+  double        feed_flow = 5;          // 进水流量
+  double        con_flow = 6;           // 浓水流量
+  double        product_flow = 7;       // 产水流量
+  double        feed_pressure = 8;      // 进水压力
+  double        con_pressure = 9;       // 浓水压力
+  double        product_pressure = 10;  // 产水压力
+  double        tmp = 11;               // 跨膜压差
+  double        flux = 12;              // 膜通量
+  double        feed_wq_turbidity = 13; // 进水浊度
+  int64         feed_wq_ph = 14;        // 进水 PH 值
+  int64         product_wq_ph = 15;     // 产水 PH 值
+  double        feed_wq_al = 16;        // 进水水质:铝
+  double        product_wq_al = 17;     // 产水水质:铝
+  double        feed_wq_fe = 18;        // 进水水质:铁
+  double        product_wq_fe = 19;     // 产水水质:铁
+  double        feed_wq_mn = 20;        // 进水水质:锰
+  double        product_wq_mn = 21;     // 产水水质:锰
+  double        feed_wq_sio2 = 22;      // 进水水质:二氧化硅
+  double        product_wq_sio2 = 23;   // 产水水质:二氧化硅
+  double        feed_wq_cod = 24;       // 进水水质:COD
+  double        product_wq_cod = 25;    // 产水水质:COD
+  double        feed_wq_p = 26;         // 进水水质:磷
+  double        product_wq_p = 27;      // 产水水质:磷
+  int64         step = 28;              // 设备当前步序值
+  string        c_time = 29;
+}
+
+message WorkingRo{
+    int64         id = 1;
+    int64         project_id = 2;
+    string        device_code = 3;
+    double       water_temperature = 4;    // 水温 摄氏度
+    double       feed_flow_1st = 5;        // 一段进水流量
+    double       con_flow_1st = 6;         // 一段浓水流量
+    double       product_flow_1st = 7;     // 一段产水流量
+    double       feed_pressure_1st = 8;    // 一段进水压力
+    double       con_pressure_1st = 9;     // 一段浓水压力
+    double       product_pressure_1st = 10; // 一段产水压力
+    double       tmp_1st = 11;              // 一段跨膜压差
+    double       flux_1st = 12;             // 一段膜通量
+    double       permeability_1st = 13;     // 一段渗透率
+    double       feed_flow_2nd = 14;        // 二段进水流量
+    double       con_flow_2nd = 15;         // 二段浓水流量
+    double       product_flow_2nd = 16;     // 二段产水流量
+    double       feed_pressure_2nd = 17;    // 二段进水压力
+    double       con_pressure_2nd = 18;     // 二段浓水压力
+    double       product_pressure_2nd = 19; // 二段产水压力
+    double       tmp_2nd = 20;              // 二段压差
+    double       flux_2nd = 21;             // 二段通量
+    double       permeability_2nd = 22;     // 二段渗透率
+    double       feed_flow_3th = 23;        // 三段进水流量
+    double       con_flow_3th = 24;         // 三段浓水流量
+    double       product_flow_3th = 25;     // 三段产水流量
+    double       feed_pressure_3th = 26;    // 三段进水压力
+    double       con_pressure_3th = 27;     // 三段浓水压力
+    double       product_pressure_3th = 28; // 三段产水压力
+    double       tmp_3th = 29;              // 三段压差
+    double       flux_3th = 30;             // 三段通量
+    double       permeability_3th = 31;     // 三段渗透率
+    double       feed_wq_turbidity = 32;    // 进水浊度
+    int64        feed_wq_ph = 33;           // 进水 PH 值
+    int64        product_wq_ph = 34;        // 产水 PH 值
+    double       feed_wq_al = 35;           // 进水水质:铝
+    double       product_wq_al = 36;        // 产水水质:铝
+    double       feed_wq_fe = 37;           // 进水水质:铁
+    double       product_wq_fe = 38;        // 产水水质:铁
+    double       feed_wq_mn = 39;           // 进水水质:锰
+    double       product_wq_mn = 40;        // 产水水质:锰
+    double       feed_wq_sio2 = 41;         // 进水水质:二氧化硅
+    double       product_wq_sio2 = 42;      // 产水水质:二氧化硅
+    double       feed_wq_cod = 43;          // 进水水质:COD
+    double       product_wq_cod = 44;       // 产水水质:COD
+    double       feed_wq_p = 45;            // 进水水质:磷
+    double       product_wq_p = 46;         // 产水水质:磷
+    int64        step = 47;                 // 设备当前步序值
+    string       c_time = 48;
+}
+
+message WorkingChest {
+  int64     id = 1;
+  int64     project_id = 2;
+  string    device_code = 3;
+  int64     switch = 4;                // 药箱液位开关 0: 关 1: 开
+  double    level = 5;                 // 液位高度
+  int64     agitator_status = 6;       // 搅拌器运行状态 0: 未运行 1:运行中
+  int64     agitator_duration = 7;     // 搅拌器运行时长
+  int64     agitator_fault_status = 8; // 搅拌器故障状态 0:正常 1:故障
+  string    c_time = 9;
+}
 
+message WorkingPump {
+  int64     id = 1;
+  int64     project_id = 2;
+  string    device_code = 3;
+  double    feed_pressure = 4; // 进水压力
+  double    out_pressure = 5;  // 出水压力
+  int64     duration = 6;      // 运行时长 单位 s
+  double    current = 7;       // 运行电流
+  double    frequency = 8;     // 运行频率
+  double    lift = 9;          // 工作扬程
+  double    efficiency = 10;    // 运行效率
+  int64     run_status = 11;    // 运行状态 0: 停机 1: 运行正常
+  int64     fault_status = 12;  // 故障状态 0: 正常 1: 故障
+  string    c_time = 13;
+}
+
+message WorkingValve {
+  int64     id = 1;
+  int64     project_id = 2;
+  string    device_code = 3;
+  int64     adjust = 4;       // 是否为调节阀门 0: 否 1: 是
+  double    opening = 5;      // 当前阀门的开度
+  int64     closed = 6;       // 关到位 全关  0: 否 1: 是
+  int64     opened = 7;       // 开到位 开到 设置的开度 0: 否 1: 是
+  int64     fault_status = 8; // 是否故障 0: 否 1: 是
+  string    c_time = 9;
+}
+
+service Organization {
+  rpc GetWorkingUfByCode(DcWorkingReq) returns(WorkingUf);
+  rpc GetWorkingRoByCode(DcWorkingReq) returns(WorkingRo);
+  rpc GetWorkingChestByCode(DcWorkingReq) returns(WorkingChest);
+  rpc GetWorkingPumpByCode(DcWorkingReq) returns(WorkingPump);
+  rpc GetWorkingValueByCode(DcWorkingReq) returns(WorkingValve);
 }

+ 42 - 0
app/cmd/organization/organization/organization.go

@@ -4,11 +4,28 @@
 package organization
 
 import (
+	"context"
+
+	"GtDataStore/app/cmd/organization/pb"
+
 	"github.com/zeromicro/go-zero/zrpc"
+	"google.golang.org/grpc"
 )
 
 type (
+	DcWorkingReq = pb.DcWorkingReq
+	WorkingChest = pb.WorkingChest
+	WorkingPump  = pb.WorkingPump
+	WorkingRo    = pb.WorkingRo
+	WorkingUf    = pb.WorkingUf
+	WorkingValve = pb.WorkingValve
+
 	Organization interface {
+		GetWorkingUfByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingUf, error)
+		GetWorkingRoByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingRo, error)
+		GetWorkingChestByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingChest, error)
+		GetWorkingPumpByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingPump, error)
+		GetWorkingValueByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingValve, error)
 	}
 
 	defaultOrganization struct {
@@ -21,3 +38,28 @@ func NewOrganization(cli zrpc.Client) Organization {
 		cli: cli,
 	}
 }
+
+func (m *defaultOrganization) GetWorkingUfByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingUf, error) {
+	client := pb.NewOrganizationClient(m.cli.Conn())
+	return client.GetWorkingUfByCode(ctx, in, opts...)
+}
+
+func (m *defaultOrganization) GetWorkingRoByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingRo, error) {
+	client := pb.NewOrganizationClient(m.cli.Conn())
+	return client.GetWorkingRoByCode(ctx, in, opts...)
+}
+
+func (m *defaultOrganization) GetWorkingChestByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingChest, error) {
+	client := pb.NewOrganizationClient(m.cli.Conn())
+	return client.GetWorkingChestByCode(ctx, in, opts...)
+}
+
+func (m *defaultOrganization) GetWorkingPumpByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingPump, error) {
+	client := pb.NewOrganizationClient(m.cli.Conn())
+	return client.GetWorkingPumpByCode(ctx, in, opts...)
+}
+
+func (m *defaultOrganization) GetWorkingValueByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingValve, error) {
+	client := pb.NewOrganizationClient(m.cli.Conn())
+	return client.GetWorkingValueByCode(ctx, in, opts...)
+}

Diff do ficheiro suprimidas por serem muito extensas
+ 1402 - 8
app/cmd/organization/pb/organization.pb.go


+ 197 - 5
app/cmd/organization/pb/organization_grpc.pb.go

@@ -1,13 +1,16 @@
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
 // versions:
-// - protoc-gen-go-grpc v1.2.0
-// - protoc             v4.23.4
+// - protoc-gen-go-grpc v1.3.0
+// - protoc             v3.21.12
 // source: organization.proto
 
 package pb
 
 import (
+	context "context"
 	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
 )
 
 // This is a compile-time assertion to ensure that this generated file
@@ -15,10 +18,23 @@ import (
 // Requires gRPC-Go v1.32.0 or later.
 const _ = grpc.SupportPackageIsVersion7
 
+const (
+	Organization_GetWorkingUfByCode_FullMethodName    = "/pb.Organization/GetWorkingUfByCode"
+	Organization_GetWorkingRoByCode_FullMethodName    = "/pb.Organization/GetWorkingRoByCode"
+	Organization_GetWorkingChestByCode_FullMethodName = "/pb.Organization/GetWorkingChestByCode"
+	Organization_GetWorkingPumpByCode_FullMethodName  = "/pb.Organization/GetWorkingPumpByCode"
+	Organization_GetWorkingValueByCode_FullMethodName = "/pb.Organization/GetWorkingValueByCode"
+)
+
 // OrganizationClient is the client API for Organization service.
 //
 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
 type OrganizationClient interface {
+	GetWorkingUfByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingUf, error)
+	GetWorkingRoByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingRo, error)
+	GetWorkingChestByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingChest, error)
+	GetWorkingPumpByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingPump, error)
+	GetWorkingValueByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingValve, error)
 }
 
 type organizationClient struct {
@@ -29,10 +45,60 @@ func NewOrganizationClient(cc grpc.ClientConnInterface) OrganizationClient {
 	return &organizationClient{cc}
 }
 
+func (c *organizationClient) GetWorkingUfByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingUf, error) {
+	out := new(WorkingUf)
+	err := c.cc.Invoke(ctx, Organization_GetWorkingUfByCode_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *organizationClient) GetWorkingRoByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingRo, error) {
+	out := new(WorkingRo)
+	err := c.cc.Invoke(ctx, Organization_GetWorkingRoByCode_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *organizationClient) GetWorkingChestByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingChest, error) {
+	out := new(WorkingChest)
+	err := c.cc.Invoke(ctx, Organization_GetWorkingChestByCode_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *organizationClient) GetWorkingPumpByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingPump, error) {
+	out := new(WorkingPump)
+	err := c.cc.Invoke(ctx, Organization_GetWorkingPumpByCode_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *organizationClient) GetWorkingValueByCode(ctx context.Context, in *DcWorkingReq, opts ...grpc.CallOption) (*WorkingValve, error) {
+	out := new(WorkingValve)
+	err := c.cc.Invoke(ctx, Organization_GetWorkingValueByCode_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 // OrganizationServer is the server API for Organization service.
 // All implementations must embed UnimplementedOrganizationServer
 // for forward compatibility
 type OrganizationServer interface {
+	GetWorkingUfByCode(context.Context, *DcWorkingReq) (*WorkingUf, error)
+	GetWorkingRoByCode(context.Context, *DcWorkingReq) (*WorkingRo, error)
+	GetWorkingChestByCode(context.Context, *DcWorkingReq) (*WorkingChest, error)
+	GetWorkingPumpByCode(context.Context, *DcWorkingReq) (*WorkingPump, error)
+	GetWorkingValueByCode(context.Context, *DcWorkingReq) (*WorkingValve, error)
 	mustEmbedUnimplementedOrganizationServer()
 }
 
@@ -40,6 +106,21 @@ type OrganizationServer interface {
 type UnimplementedOrganizationServer struct {
 }
 
+func (UnimplementedOrganizationServer) GetWorkingUfByCode(context.Context, *DcWorkingReq) (*WorkingUf, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetWorkingUfByCode not implemented")
+}
+func (UnimplementedOrganizationServer) GetWorkingRoByCode(context.Context, *DcWorkingReq) (*WorkingRo, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetWorkingRoByCode not implemented")
+}
+func (UnimplementedOrganizationServer) GetWorkingChestByCode(context.Context, *DcWorkingReq) (*WorkingChest, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetWorkingChestByCode not implemented")
+}
+func (UnimplementedOrganizationServer) GetWorkingPumpByCode(context.Context, *DcWorkingReq) (*WorkingPump, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetWorkingPumpByCode not implemented")
+}
+func (UnimplementedOrganizationServer) GetWorkingValueByCode(context.Context, *DcWorkingReq) (*WorkingValve, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetWorkingValueByCode not implemented")
+}
 func (UnimplementedOrganizationServer) mustEmbedUnimplementedOrganizationServer() {}
 
 // UnsafeOrganizationServer may be embedded to opt out of forward compatibility for this service.
@@ -53,13 +134,124 @@ func RegisterOrganizationServer(s grpc.ServiceRegistrar, srv OrganizationServer)
 	s.RegisterService(&Organization_ServiceDesc, srv)
 }
 
+func _Organization_GetWorkingUfByCode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DcWorkingReq)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(OrganizationServer).GetWorkingUfByCode(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: Organization_GetWorkingUfByCode_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(OrganizationServer).GetWorkingUfByCode(ctx, req.(*DcWorkingReq))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Organization_GetWorkingRoByCode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DcWorkingReq)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(OrganizationServer).GetWorkingRoByCode(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: Organization_GetWorkingRoByCode_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(OrganizationServer).GetWorkingRoByCode(ctx, req.(*DcWorkingReq))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Organization_GetWorkingChestByCode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DcWorkingReq)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(OrganizationServer).GetWorkingChestByCode(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: Organization_GetWorkingChestByCode_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(OrganizationServer).GetWorkingChestByCode(ctx, req.(*DcWorkingReq))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Organization_GetWorkingPumpByCode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DcWorkingReq)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(OrganizationServer).GetWorkingPumpByCode(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: Organization_GetWorkingPumpByCode_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(OrganizationServer).GetWorkingPumpByCode(ctx, req.(*DcWorkingReq))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Organization_GetWorkingValueByCode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DcWorkingReq)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(OrganizationServer).GetWorkingValueByCode(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: Organization_GetWorkingValueByCode_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(OrganizationServer).GetWorkingValueByCode(ctx, req.(*DcWorkingReq))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 // Organization_ServiceDesc is the grpc.ServiceDesc for Organization service.
 // It's only intended for direct use with grpc.RegisterService,
 // and not to be introspected or modified (even as a copy)
 var Organization_ServiceDesc = grpc.ServiceDesc{
 	ServiceName: "pb.Organization",
 	HandlerType: (*OrganizationServer)(nil),
-	Methods:     []grpc.MethodDesc{},
-	Streams:     []grpc.StreamDesc{},
-	Metadata:    "organization.proto",
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "GetWorkingUfByCode",
+			Handler:    _Organization_GetWorkingUfByCode_Handler,
+		},
+		{
+			MethodName: "GetWorkingRoByCode",
+			Handler:    _Organization_GetWorkingRoByCode_Handler,
+		},
+		{
+			MethodName: "GetWorkingChestByCode",
+			Handler:    _Organization_GetWorkingChestByCode_Handler,
+		},
+		{
+			MethodName: "GetWorkingPumpByCode",
+			Handler:    _Organization_GetWorkingPumpByCode_Handler,
+		},
+		{
+			MethodName: "GetWorkingValueByCode",
+			Handler:    _Organization_GetWorkingValueByCode_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "organization.proto",
 }

+ 21 - 1
app/model/dcWorkingChestModel.go

@@ -1,6 +1,11 @@
 package model
 
-import "github.com/zeromicro/go-zero/core/stores/sqlx"
+import (
+	"context"
+	"fmt"
+	"github.com/zeromicro/go-zero/core/stores/sqlc"
+	"github.com/zeromicro/go-zero/core/stores/sqlx"
+)
 
 var _ DcWorkingChestModel = (*customDcWorkingChestModel)(nil)
 
@@ -9,6 +14,7 @@ type (
 	// and implement the added methods in customDcWorkingChestModel.
 	DcWorkingChestModel interface {
 		dcWorkingChestModel
+		FindOneByCode(ctx context.Context, projectId int64, deviceCode string) (*DcWorkingChest, error)
 	}
 
 	customDcWorkingChestModel struct {
@@ -22,3 +28,17 @@ func NewDcWorkingChestModel(conn sqlx.SqlConn) DcWorkingChestModel {
 		defaultDcWorkingChestModel: newDcWorkingChestModel(conn),
 	}
 }
+
+func (m *defaultDcWorkingChestModel) FindOneByCode(ctx context.Context, projectId int64, deviceCode string) (*DcWorkingChest, error) {
+	var resp DcWorkingChest
+	query := fmt.Sprintf("select %s from %s where `project_id` = ? and `device_code` = ? order by c_time desc limit 1", dcProjectConfigRows, m.table)
+	err := m.conn.QueryRowCtx(ctx, &resp, query, projectId, deviceCode)
+	switch err {
+	case nil:
+		return &resp, nil
+	case sqlc.ErrNotFound:
+		return nil, ErrNotFound
+	default:
+		return nil, err
+	}
+}

+ 21 - 1
app/model/dcWorkingPumpModel.go

@@ -1,6 +1,11 @@
 package model
 
-import "github.com/zeromicro/go-zero/core/stores/sqlx"
+import (
+	"context"
+	"fmt"
+	"github.com/zeromicro/go-zero/core/stores/sqlc"
+	"github.com/zeromicro/go-zero/core/stores/sqlx"
+)
 
 var _ DcWorkingPumpModel = (*customDcWorkingPumpModel)(nil)
 
@@ -9,6 +14,7 @@ type (
 	// and implement the added methods in customDcWorkingPumpModel.
 	DcWorkingPumpModel interface {
 		dcWorkingPumpModel
+		FindOneByCode(ctx context.Context, projectId int64, deviceCode string) (*DcWorkingPump, error)
 	}
 
 	customDcWorkingPumpModel struct {
@@ -22,3 +28,17 @@ func NewDcWorkingPumpModel(conn sqlx.SqlConn) DcWorkingPumpModel {
 		defaultDcWorkingPumpModel: newDcWorkingPumpModel(conn),
 	}
 }
+
+func (m *defaultDcWorkingPumpModel) FindOneByCode(ctx context.Context, projectId int64, deviceCode string) (*DcWorkingPump, error) {
+	var resp DcWorkingPump
+	query := fmt.Sprintf("select %s from %s where `project_id` = ? and `device_code` = ? order by c_time desc limit 1", dcProjectConfigRows, m.table)
+	err := m.conn.QueryRowCtx(ctx, &resp, query, projectId, deviceCode)
+	switch err {
+	case nil:
+		return &resp, nil
+	case sqlc.ErrNotFound:
+		return nil, ErrNotFound
+	default:
+		return nil, err
+	}
+}

+ 21 - 1
app/model/dcWorkingRoModel.go

@@ -1,6 +1,11 @@
 package model
 
-import "github.com/zeromicro/go-zero/core/stores/sqlx"
+import (
+	"context"
+	"fmt"
+	"github.com/zeromicro/go-zero/core/stores/sqlc"
+	"github.com/zeromicro/go-zero/core/stores/sqlx"
+)
 
 var _ DcWorkingRoModel = (*customDcWorkingRoModel)(nil)
 
@@ -9,6 +14,7 @@ type (
 	// and implement the added methods in customDcWorkingRoModel.
 	DcWorkingRoModel interface {
 		dcWorkingRoModel
+		FindOneByCode(ctx context.Context, projectId int64, deviceCode string) (*DcWorkingRo, error)
 	}
 
 	customDcWorkingRoModel struct {
@@ -22,3 +28,17 @@ func NewDcWorkingRoModel(conn sqlx.SqlConn) DcWorkingRoModel {
 		defaultDcWorkingRoModel: newDcWorkingRoModel(conn),
 	}
 }
+
+func (m *defaultDcWorkingRoModel) FindOneByCode(ctx context.Context, projectId int64, deviceCode string) (*DcWorkingRo, error) {
+	var resp DcWorkingRo
+	query := fmt.Sprintf("select %s from %s where `project_id` = ? and `device_code` = ? order by c_time desc limit 1", dcProjectConfigRows, m.table)
+	err := m.conn.QueryRowCtx(ctx, &resp, query, projectId, deviceCode)
+	switch err {
+	case nil:
+		return &resp, nil
+	case sqlc.ErrNotFound:
+		return nil, ErrNotFound
+	default:
+		return nil, err
+	}
+}

+ 21 - 1
app/model/dcWorkingUfModel.go

@@ -1,6 +1,11 @@
 package model
 
-import "github.com/zeromicro/go-zero/core/stores/sqlx"
+import (
+	"context"
+	"fmt"
+	"github.com/zeromicro/go-zero/core/stores/sqlc"
+	"github.com/zeromicro/go-zero/core/stores/sqlx"
+)
 
 var _ DcWorkingUfModel = (*customDcWorkingUfModel)(nil)
 
@@ -9,6 +14,7 @@ type (
 	// and implement the added methods in customDcWorkingUfModel.
 	DcWorkingUfModel interface {
 		dcWorkingUfModel
+		FindOneByCode(ctx context.Context, projectId int64, deviceCode string) (*DcWorkingUf, error)
 	}
 
 	customDcWorkingUfModel struct {
@@ -22,3 +28,17 @@ func NewDcWorkingUfModel(conn sqlx.SqlConn) DcWorkingUfModel {
 		defaultDcWorkingUfModel: newDcWorkingUfModel(conn),
 	}
 }
+
+func (m *defaultDcWorkingUfModel) FindOneByCode(ctx context.Context, projectId int64, deviceCode string) (*DcWorkingUf, error) {
+	var resp DcWorkingUf
+	query := fmt.Sprintf("select %s from %s where `project_id` = ? and `device_code` = ? order by c_time desc limit 1", dcProjectConfigRows, m.table)
+	err := m.conn.QueryRowCtx(ctx, &resp, query, projectId, deviceCode)
+	switch err {
+	case nil:
+		return &resp, nil
+	case sqlc.ErrNotFound:
+		return nil, ErrNotFound
+	default:
+		return nil, err
+	}
+}

+ 20 - 1
app/model/dcWorkingValveModel.go

@@ -1,6 +1,11 @@
 package model
 
-import "github.com/zeromicro/go-zero/core/stores/sqlx"
+import (
+	"context"
+	"fmt"
+	"github.com/zeromicro/go-zero/core/stores/sqlc"
+	"github.com/zeromicro/go-zero/core/stores/sqlx"
+)
 
 var _ DcWorkingValveModel = (*customDcWorkingValveModel)(nil)
 
@@ -9,6 +14,7 @@ type (
 	// and implement the added methods in customDcWorkingValveModel.
 	DcWorkingValveModel interface {
 		dcWorkingValveModel
+		FindOneByCode(ctx context.Context, projectId int64, deviceCode string) (*DcWorkingValve, error)
 	}
 
 	customDcWorkingValveModel struct {
@@ -22,3 +28,16 @@ func NewDcWorkingValveModel(conn sqlx.SqlConn) DcWorkingValveModel {
 		defaultDcWorkingValveModel: newDcWorkingValveModel(conn),
 	}
 }
+func (m *defaultDcWorkingValveModel) FindOneByCode(ctx context.Context, projectId int64, deviceCode string) (*DcWorkingValve, error) {
+	var resp DcWorkingValve
+	query := fmt.Sprintf("select %s from %s where `project_id` = ? and `device_code` = ? order by c_time desc limit 1", dcProjectConfigRows, m.table)
+	err := m.conn.QueryRowCtx(ctx, &resp, query, projectId, deviceCode)
+	switch err {
+	case nil:
+		return &resp, nil
+	case sqlc.ErrNotFound:
+		return nil, ErrNotFound
+	default:
+		return nil, err
+	}
+}

+ 2 - 1
go.mod

@@ -3,6 +3,7 @@ module GtDataStore
 go 1.19
 
 require (
+	github.com/go-redis/redis/v8 v8.11.5
 	github.com/zeromicro/go-zero v1.6.0
 	google.golang.org/grpc v1.59.0
 	google.golang.org/protobuf v1.31.0
@@ -23,7 +24,6 @@ require (
 	github.com/go-openapi/jsonpointer v0.19.6 // indirect
 	github.com/go-openapi/jsonreference v0.20.2 // indirect
 	github.com/go-openapi/swag v0.22.4 // indirect
-	github.com/go-redis/redis/v8 v8.11.5 // indirect
 	github.com/go-sql-driver/mysql v1.7.1 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang/mock v1.6.0 // indirect
@@ -33,6 +33,7 @@ require (
 	github.com/google/gofuzz v1.2.0 // indirect
 	github.com/google/uuid v1.4.0 // indirect
 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
+	github.com/jinzhu/copier v0.4.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect

+ 2 - 0
go.sum

@@ -66,6 +66,8 @@ github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk=
 github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
+github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
+github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=

+ 2 - 0
vendor/github.com/jinzhu/copier/.gitignore

@@ -0,0 +1,2 @@
+.idea/
+ttt/

+ 20 - 0
vendor/github.com/jinzhu/copier/License

@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Jinzhu
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 132 - 0
vendor/github.com/jinzhu/copier/README.md

@@ -0,0 +1,132 @@
+# Copier
+
+  I am a copier, I copy everything from one to another
+
+[![test status](https://github.com/jinzhu/copier/workflows/tests/badge.svg?branch=master "test status")](https://github.com/jinzhu/copier/actions)
+
+## Features
+
+* Copy from field to field with same name
+* Copy from method to field with same name
+* Copy from field to method with same name
+* Copy from slice to slice
+* Copy from struct to slice
+* Copy from map to map
+* Enforce copying a field with a tag
+* Ignore a field with a tag
+* Deep Copy
+
+## Usage
+
+```go
+package main
+
+import (
+	"fmt"
+	"github.com/jinzhu/copier"
+)
+
+type User struct {
+	Name        string
+	Role        string
+	Age         int32
+	EmployeeCode int64 `copier:"EmployeeNum"` // specify field name
+
+	// Explicitly ignored in the destination struct.
+	Salary   int
+}
+
+func (user *User) DoubleAge() int32 {
+	return 2 * user.Age
+}
+
+// Tags in the destination Struct provide instructions to copier.Copy to ignore
+// or enforce copying and to panic or return an error if a field was not copied.
+type Employee struct {
+	// Tell copier.Copy to panic if this field is not copied.
+	Name      string `copier:"must"`
+
+	// Tell copier.Copy to return an error if this field is not copied.
+	Age       int32  `copier:"must,nopanic"`
+
+	// Tell copier.Copy to explicitly ignore copying this field.
+	Salary    int    `copier:"-"`
+
+	DoubleAge int32
+	EmployeeId int64 `copier:"EmployeeNum"` // specify field name
+	SuperRole string
+}
+
+func (employee *Employee) Role(role string) {
+	employee.SuperRole = "Super " + role
+}
+
+func main() {
+	var (
+		user      = User{Name: "Jinzhu", Age: 18, Role: "Admin", Salary: 200000}
+		users     = []User{{Name: "Jinzhu", Age: 18, Role: "Admin", Salary: 100000}, {Name: "jinzhu 2", Age: 30, Role: "Dev", Salary: 60000}}
+		employee  = Employee{Salary: 150000}
+		employees = []Employee{}
+	)
+
+	copier.Copy(&employee, &user)
+
+	fmt.Printf("%#v \n", employee)
+	// Employee{
+	//    Name: "Jinzhu",           // Copy from field
+	//    Age: 18,                  // Copy from field
+	//    Salary:150000,            // Copying explicitly ignored
+	//    DoubleAge: 36,            // Copy from method
+	//    EmployeeId: 0,            // Ignored
+	//    SuperRole: "Super Admin", // Copy to method
+	// }
+
+	// Copy struct to slice
+	copier.Copy(&employees, &user)
+
+	fmt.Printf("%#v \n", employees)
+	// []Employee{
+	//   {Name: "Jinzhu", Age: 18, Salary:0, DoubleAge: 36, EmployeeId: 0, SuperRole: "Super Admin"}
+	// }
+
+	// Copy slice to slice
+	employees = []Employee{}
+	copier.Copy(&employees, &users)
+
+	fmt.Printf("%#v \n", employees)
+	// []Employee{
+	//   {Name: "Jinzhu", Age: 18, Salary:0, DoubleAge: 36, EmployeeId: 0, SuperRole: "Super Admin"},
+	//   {Name: "jinzhu 2", Age: 30, Salary:0, DoubleAge: 60, EmployeeId: 0, SuperRole: "Super Dev"},
+	// }
+
+ 	// Copy map to map
+	map1 := map[int]int{3: 6, 4: 8}
+	map2 := map[int32]int8{}
+	copier.Copy(&map2, map1)
+
+	fmt.Printf("%#v \n", map2)
+	// map[int32]int8{3:6, 4:8}
+}
+```
+
+### Copy with Option
+
+```go
+copier.CopyWithOption(&to, &from, copier.Option{IgnoreEmpty: true, DeepCopy: true})
+```
+
+## Contributing
+
+You can help to make the project better, check out [http://gorm.io/contribute.html](http://gorm.io/contribute.html) for things you can do.
+
+# Author
+
+**jinzhu**
+
+* <http://github.com/jinzhu>
+* <wosmvp@gmail.com>
+* <http://twitter.com/zhangjinzhu>
+
+## License
+
+Released under the [MIT License](https://github.com/jinzhu/copier/blob/master/License).

+ 828 - 0
vendor/github.com/jinzhu/copier/copier.go

@@ -0,0 +1,828 @@
+package copier
+
+import (
+	"database/sql"
+	"database/sql/driver"
+	"fmt"
+	"reflect"
+	"strings"
+	"sync"
+	"unicode"
+)
+
+// These flags define options for tag handling
+const (
+	// Denotes that a destination field must be copied to. If copying fails then a panic will ensue.
+	tagMust uint8 = 1 << iota
+
+	// Denotes that the program should not panic when the must flag is on and
+	// value is not copied. The program will return an error instead.
+	tagNoPanic
+
+	// Ignore a destination field from being copied to.
+	tagIgnore
+
+	// Denotes that the value as been copied
+	hasCopied
+
+	// Some default converter types for a nicer syntax
+	String  string  = ""
+	Bool    bool    = false
+	Int     int     = 0
+	Float32 float32 = 0
+	Float64 float64 = 0
+)
+
+// Option sets copy options
+type Option struct {
+	// setting this value to true will ignore copying zero values of all the fields, including bools, as well as a
+	// struct having all it's fields set to their zero values respectively (see IsZero() in reflect/value.go)
+	IgnoreEmpty   bool
+	CaseSensitive bool
+	DeepCopy      bool
+	Converters    []TypeConverter
+	// Custom field name mappings to copy values with different names in `fromValue` and `toValue` types.
+	// Examples can be found in `copier_field_name_mapping_test.go`.
+	FieldNameMapping []FieldNameMapping
+}
+
+func (opt Option) converters() map[converterPair]TypeConverter {
+	var converters = map[converterPair]TypeConverter{}
+
+	// save converters into map for faster lookup
+	for i := range opt.Converters {
+		pair := converterPair{
+			SrcType: reflect.TypeOf(opt.Converters[i].SrcType),
+			DstType: reflect.TypeOf(opt.Converters[i].DstType),
+		}
+
+		converters[pair] = opt.Converters[i]
+	}
+
+	return converters
+}
+
+type TypeConverter struct {
+	SrcType interface{}
+	DstType interface{}
+	Fn      func(src interface{}) (dst interface{}, err error)
+}
+
+type converterPair struct {
+	SrcType reflect.Type
+	DstType reflect.Type
+}
+
+func (opt Option) fieldNameMapping() map[converterPair]FieldNameMapping {
+	var mapping = map[converterPair]FieldNameMapping{}
+
+	for i := range opt.FieldNameMapping {
+		pair := converterPair{
+			SrcType: reflect.TypeOf(opt.FieldNameMapping[i].SrcType),
+			DstType: reflect.TypeOf(opt.FieldNameMapping[i].DstType),
+		}
+
+		mapping[pair] = opt.FieldNameMapping[i]
+	}
+
+	return mapping
+}
+
+type FieldNameMapping struct {
+	SrcType interface{}
+	DstType interface{}
+	Mapping map[string]string
+}
+
+// Tag Flags
+type flags struct {
+	BitFlags  map[string]uint8
+	SrcNames  tagNameMapping
+	DestNames tagNameMapping
+}
+
+// Field Tag name mapping
+type tagNameMapping struct {
+	FieldNameToTag map[string]string
+	TagToFieldName map[string]string
+}
+
+// Copy copy things
+func Copy(toValue interface{}, fromValue interface{}) (err error) {
+	return copier(toValue, fromValue, Option{})
+}
+
+// CopyWithOption copy with option
+func CopyWithOption(toValue interface{}, fromValue interface{}, opt Option) (err error) {
+	return copier(toValue, fromValue, opt)
+}
+
+func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) {
+	var (
+		isSlice    bool
+		amount     = 1
+		from       = indirect(reflect.ValueOf(fromValue))
+		to         = indirect(reflect.ValueOf(toValue))
+		converters = opt.converters()
+		mappings   = opt.fieldNameMapping()
+	)
+
+	if !to.CanAddr() {
+		return ErrInvalidCopyDestination
+	}
+
+	// Return is from value is invalid
+	if !from.IsValid() {
+		return ErrInvalidCopyFrom
+	}
+
+	fromType, isPtrFrom := indirectType(from.Type())
+	toType, _ := indirectType(to.Type())
+
+	if fromType.Kind() == reflect.Interface {
+		fromType = reflect.TypeOf(from.Interface())
+	}
+
+	if toType.Kind() == reflect.Interface {
+		toType, _ = indirectType(reflect.TypeOf(to.Interface()))
+		oldTo := to
+		to = reflect.New(reflect.TypeOf(to.Interface())).Elem()
+		defer func() {
+			oldTo.Set(to)
+		}()
+	}
+
+	// Just set it if possible to assign for normal types
+	if from.Kind() != reflect.Slice && from.Kind() != reflect.Struct && from.Kind() != reflect.Map && (from.Type().AssignableTo(to.Type()) || from.Type().ConvertibleTo(to.Type())) {
+		if !isPtrFrom || !opt.DeepCopy {
+			to.Set(from.Convert(to.Type()))
+		} else {
+			fromCopy := reflect.New(from.Type())
+			fromCopy.Set(from.Elem())
+			to.Set(fromCopy.Convert(to.Type()))
+		}
+		return
+	}
+
+	if from.Kind() != reflect.Slice && fromType.Kind() == reflect.Map && toType.Kind() == reflect.Map {
+		if !fromType.Key().ConvertibleTo(toType.Key()) {
+			return ErrMapKeyNotMatch
+		}
+
+		if to.IsNil() {
+			to.Set(reflect.MakeMapWithSize(toType, from.Len()))
+		}
+
+		for _, k := range from.MapKeys() {
+			toKey := indirect(reflect.New(toType.Key()))
+			isSet, err := set(toKey, k, opt.DeepCopy, converters)
+			if err != nil {
+				return err
+			}
+			if !isSet {
+				return fmt.Errorf("%w map, old key: %v, new key: %v", ErrNotSupported, k.Type(), toType.Key())
+			}
+
+			elemType := toType.Elem()
+			if elemType.Kind() != reflect.Slice {
+				elemType, _ = indirectType(elemType)
+			}
+			toValue := indirect(reflect.New(elemType))
+			isSet, err = set(toValue, from.MapIndex(k), opt.DeepCopy, converters)
+			if err != nil {
+				return err
+			}
+			if !isSet {
+				if err = copier(toValue.Addr().Interface(), from.MapIndex(k).Interface(), opt); err != nil {
+					return err
+				}
+			}
+
+			for {
+				if elemType == toType.Elem() {
+					to.SetMapIndex(toKey, toValue)
+					break
+				}
+				elemType = reflect.PtrTo(elemType)
+				toValue = toValue.Addr()
+			}
+		}
+		return
+	}
+
+	if from.Kind() == reflect.Slice && to.Kind() == reflect.Slice {
+		if to.IsNil() {
+			slice := reflect.MakeSlice(reflect.SliceOf(to.Type().Elem()), from.Len(), from.Cap())
+			to.Set(slice)
+		}
+		if fromType.ConvertibleTo(toType) {
+			for i := 0; i < from.Len(); i++ {
+				if to.Len() < i+1 {
+					to.Set(reflect.Append(to, reflect.New(to.Type().Elem()).Elem()))
+				}
+				isSet, err := set(to.Index(i), from.Index(i), opt.DeepCopy, converters)
+				if err != nil {
+					return err
+				}
+				if !isSet {
+					// ignore error while copy slice element
+					err = copier(to.Index(i).Addr().Interface(), from.Index(i).Interface(), opt)
+					if err != nil {
+						continue
+					}
+				}
+			}
+			return
+		}
+	}
+
+	if fromType.Kind() != reflect.Struct || toType.Kind() != reflect.Struct {
+		// skip not supported type
+		return
+	}
+
+	if len(converters) > 0 {
+		if ok, e := set(to, from, opt.DeepCopy, converters); e == nil && ok {
+			// converter supported
+			return
+		}
+	}
+
+	if from.Kind() == reflect.Slice || to.Kind() == reflect.Slice {
+		isSlice = true
+		if from.Kind() == reflect.Slice {
+			amount = from.Len()
+		}
+	}
+
+	for i := 0; i < amount; i++ {
+		var dest, source reflect.Value
+
+		if isSlice {
+			// source
+			if from.Kind() == reflect.Slice {
+				source = indirect(from.Index(i))
+			} else {
+				source = indirect(from)
+			}
+			// dest
+			dest = indirect(reflect.New(toType).Elem())
+		} else {
+			source = indirect(from)
+			dest = indirect(to)
+		}
+
+		if len(converters) > 0 {
+			if ok, e := set(dest, source, opt.DeepCopy, converters); e == nil && ok {
+				if isSlice {
+					// FIXME: maybe should check the other types?
+					if to.Type().Elem().Kind() == reflect.Ptr {
+						to.Index(i).Set(dest.Addr())
+					} else {
+						if to.Len() < i+1 {
+							reflect.Append(to, dest)
+						} else {
+							to.Index(i).Set(dest)
+						}
+					}
+				} else {
+					to.Set(dest)
+				}
+
+				continue
+			}
+		}
+
+		destKind := dest.Kind()
+		initDest := false
+		if destKind == reflect.Interface {
+			initDest = true
+			dest = indirect(reflect.New(toType))
+		}
+
+		// Get tag options
+		flgs, err := getFlags(dest, source, toType, fromType)
+		if err != nil {
+			return err
+		}
+
+		// check source
+		if source.IsValid() {
+			copyUnexportedStructFields(dest, source)
+
+			// Copy from source field to dest field or method
+			fromTypeFields := deepFields(fromType)
+			for _, field := range fromTypeFields {
+				name := field.Name
+
+				// Get bit flags for field
+				fieldFlags := flgs.BitFlags[name]
+
+				// Check if we should ignore copying
+				if (fieldFlags & tagIgnore) != 0 {
+					continue
+				}
+
+				fieldNamesMapping := getFieldNamesMapping(mappings, fromType, toType)
+
+				srcFieldName, destFieldName := getFieldName(name, flgs, fieldNamesMapping)
+				if fromField := fieldByNameOrZeroValue(source, srcFieldName); fromField.IsValid() && !shouldIgnore(fromField, opt.IgnoreEmpty) {
+					// process for nested anonymous field
+					destFieldNotSet := false
+					if f, ok := dest.Type().FieldByName(destFieldName); ok {
+						// only initialize parent embedded struct pointer in the path
+						for idx := range f.Index[:len(f.Index)-1] {
+							destField := dest.FieldByIndex(f.Index[:idx+1])
+
+							if destField.Kind() != reflect.Ptr {
+								continue
+							}
+
+							if !destField.IsNil() {
+								continue
+							}
+							if !destField.CanSet() {
+								destFieldNotSet = true
+								break
+							}
+
+							// destField is a nil pointer that can be set
+							newValue := reflect.New(destField.Type().Elem())
+							destField.Set(newValue)
+						}
+					}
+
+					if destFieldNotSet {
+						break
+					}
+
+					toField := fieldByName(dest, destFieldName, opt.CaseSensitive)
+					if toField.IsValid() {
+						if toField.CanSet() {
+							isSet, err := set(toField, fromField, opt.DeepCopy, converters)
+							if err != nil {
+								return err
+							}
+							if !isSet {
+								if err := copier(toField.Addr().Interface(), fromField.Interface(), opt); err != nil {
+									return err
+								}
+							}
+							if fieldFlags != 0 {
+								// Note that a copy was made
+								flgs.BitFlags[name] = fieldFlags | hasCopied
+							}
+						}
+					} else {
+						// try to set to method
+						var toMethod reflect.Value
+						if dest.CanAddr() {
+							toMethod = dest.Addr().MethodByName(destFieldName)
+						} else {
+							toMethod = dest.MethodByName(destFieldName)
+						}
+
+						if toMethod.IsValid() && toMethod.Type().NumIn() == 1 && fromField.Type().AssignableTo(toMethod.Type().In(0)) {
+							toMethod.Call([]reflect.Value{fromField})
+						}
+					}
+				}
+			}
+
+			// Copy from from method to dest field
+			for _, field := range deepFields(toType) {
+				name := field.Name
+				srcFieldName, destFieldName := getFieldName(name, flgs, getFieldNamesMapping(mappings, fromType, toType))
+
+				var fromMethod reflect.Value
+				if source.CanAddr() {
+					fromMethod = source.Addr().MethodByName(srcFieldName)
+				} else {
+					fromMethod = source.MethodByName(srcFieldName)
+				}
+
+				if fromMethod.IsValid() && fromMethod.Type().NumIn() == 0 && fromMethod.Type().NumOut() == 1 && !shouldIgnore(fromMethod, opt.IgnoreEmpty) {
+					if toField := fieldByName(dest, destFieldName, opt.CaseSensitive); toField.IsValid() && toField.CanSet() {
+						values := fromMethod.Call([]reflect.Value{})
+						if len(values) >= 1 {
+							set(toField, values[0], opt.DeepCopy, converters)
+						}
+					}
+				}
+			}
+		}
+
+		if isSlice && to.Kind() == reflect.Slice {
+			if dest.Addr().Type().AssignableTo(to.Type().Elem()) {
+				if to.Len() < i+1 {
+					to.Set(reflect.Append(to, dest.Addr()))
+				} else {
+					isSet, err := set(to.Index(i), dest.Addr(), opt.DeepCopy, converters)
+					if err != nil {
+						return err
+					}
+					if !isSet {
+						// ignore error while copy slice element
+						err = copier(to.Index(i).Addr().Interface(), dest.Addr().Interface(), opt)
+						if err != nil {
+							continue
+						}
+					}
+				}
+			} else if dest.Type().AssignableTo(to.Type().Elem()) {
+				if to.Len() < i+1 {
+					to.Set(reflect.Append(to, dest))
+				} else {
+					isSet, err := set(to.Index(i), dest, opt.DeepCopy, converters)
+					if err != nil {
+						return err
+					}
+					if !isSet {
+						// ignore error while copy slice element
+						err = copier(to.Index(i).Addr().Interface(), dest.Interface(), opt)
+						if err != nil {
+							continue
+						}
+					}
+				}
+			}
+		} else if initDest {
+			to.Set(dest)
+		}
+
+		err = checkBitFlags(flgs.BitFlags)
+	}
+
+	return
+}
+
+func getFieldNamesMapping(mappings map[converterPair]FieldNameMapping, fromType reflect.Type, toType reflect.Type) map[string]string {
+	var fieldNamesMapping map[string]string
+
+	if len(mappings) > 0 {
+		pair := converterPair{
+			SrcType: fromType,
+			DstType: toType,
+		}
+		if v, ok := mappings[pair]; ok {
+			fieldNamesMapping = v.Mapping
+		}
+	}
+	return fieldNamesMapping
+}
+
+func fieldByNameOrZeroValue(source reflect.Value, fieldName string) (value reflect.Value) {
+	defer func() {
+		if err := recover(); err != nil {
+			value = reflect.Value{}
+		}
+	}()
+
+	return source.FieldByName(fieldName)
+}
+
+func copyUnexportedStructFields(to, from reflect.Value) {
+	if from.Kind() != reflect.Struct || to.Kind() != reflect.Struct || !from.Type().AssignableTo(to.Type()) {
+		return
+	}
+
+	// create a shallow copy of 'to' to get all fields
+	tmp := indirect(reflect.New(to.Type()))
+	tmp.Set(from)
+
+	// revert exported fields
+	for i := 0; i < to.NumField(); i++ {
+		if tmp.Field(i).CanSet() {
+			tmp.Field(i).Set(to.Field(i))
+		}
+	}
+	to.Set(tmp)
+}
+
+func shouldIgnore(v reflect.Value, ignoreEmpty bool) bool {
+	return ignoreEmpty && v.IsZero()
+}
+
+var deepFieldsLock sync.RWMutex
+var deepFieldsMap = make(map[reflect.Type][]reflect.StructField)
+
+func deepFields(reflectType reflect.Type) []reflect.StructField {
+	deepFieldsLock.RLock()
+	cache, ok := deepFieldsMap[reflectType]
+	deepFieldsLock.RUnlock()
+	if ok {
+		return cache
+	}
+	var res []reflect.StructField
+	if reflectType, _ = indirectType(reflectType); reflectType.Kind() == reflect.Struct {
+		fields := make([]reflect.StructField, 0, reflectType.NumField())
+
+		for i := 0; i < reflectType.NumField(); i++ {
+			v := reflectType.Field(i)
+			// PkgPath is the package path that qualifies a lower case (unexported)
+			// field name. It is empty for upper case (exported) field names.
+			// See https://golang.org/ref/spec#Uniqueness_of_identifiers
+			if v.PkgPath == "" {
+				fields = append(fields, v)
+				if v.Anonymous {
+					// also consider fields of anonymous fields as fields of the root
+					fields = append(fields, deepFields(v.Type)...)
+				}
+			}
+		}
+		res = fields
+	}
+
+	deepFieldsLock.Lock()
+	deepFieldsMap[reflectType] = res
+	deepFieldsLock.Unlock()
+	return res
+}
+
+func indirect(reflectValue reflect.Value) reflect.Value {
+	for reflectValue.Kind() == reflect.Ptr {
+		reflectValue = reflectValue.Elem()
+	}
+	return reflectValue
+}
+
+func indirectType(reflectType reflect.Type) (_ reflect.Type, isPtr bool) {
+	for reflectType.Kind() == reflect.Ptr || reflectType.Kind() == reflect.Slice {
+		reflectType = reflectType.Elem()
+		isPtr = true
+	}
+	return reflectType, isPtr
+}
+
+func set(to, from reflect.Value, deepCopy bool, converters map[converterPair]TypeConverter) (bool, error) {
+	if !from.IsValid() {
+		return true, nil
+	}
+	if ok, err := lookupAndCopyWithConverter(to, from, converters); err != nil {
+		return false, err
+	} else if ok {
+		return true, nil
+	}
+
+	if to.Kind() == reflect.Ptr {
+		// set `to` to nil if from is nil
+		if from.Kind() == reflect.Ptr && from.IsNil() {
+			to.Set(reflect.Zero(to.Type()))
+			return true, nil
+		} else if to.IsNil() {
+			// `from`         -> `to`
+			// sql.NullString -> *string
+			if fromValuer, ok := driverValuer(from); ok {
+				v, err := fromValuer.Value()
+				if err != nil {
+					return true, nil
+				}
+				// if `from` is not valid do nothing with `to`
+				if v == nil {
+					return true, nil
+				}
+			}
+			// allocate new `to` variable with default value (eg. *string -> new(string))
+			to.Set(reflect.New(to.Type().Elem()))
+		}
+		// depointer `to`
+		to = to.Elem()
+	}
+
+	if deepCopy {
+		toKind := to.Kind()
+		if toKind == reflect.Interface && to.IsNil() {
+			if reflect.TypeOf(from.Interface()) != nil {
+				to.Set(reflect.New(reflect.TypeOf(from.Interface())).Elem())
+				toKind = reflect.TypeOf(to.Interface()).Kind()
+			}
+		}
+		if from.Kind() == reflect.Ptr && from.IsNil() {
+			return true, nil
+		}
+		if _, ok := to.Addr().Interface().(sql.Scanner); !ok && (toKind == reflect.Struct || toKind == reflect.Map || toKind == reflect.Slice) {
+			return false, nil
+		}
+	}
+
+	if from.Type().ConvertibleTo(to.Type()) {
+		to.Set(from.Convert(to.Type()))
+	} else if toScanner, ok := to.Addr().Interface().(sql.Scanner); ok {
+		// `from`  -> `to`
+		// *string -> sql.NullString
+		if from.Kind() == reflect.Ptr {
+			// if `from` is nil do nothing with `to`
+			if from.IsNil() {
+				return true, nil
+			}
+			// depointer `from`
+			from = indirect(from)
+		}
+		// `from` -> `to`
+		// string -> sql.NullString
+		// set `to` by invoking method Scan(`from`)
+		err := toScanner.Scan(from.Interface())
+		if err != nil {
+			return false, nil
+		}
+	} else if fromValuer, ok := driverValuer(from); ok {
+		// `from`         -> `to`
+		// sql.NullString -> string
+		v, err := fromValuer.Value()
+		if err != nil {
+			return false, nil
+		}
+		// if `from` is not valid do nothing with `to`
+		if v == nil {
+			return true, nil
+		}
+		rv := reflect.ValueOf(v)
+		if rv.Type().AssignableTo(to.Type()) {
+			to.Set(rv)
+		} else if to.CanSet() && rv.Type().ConvertibleTo(to.Type()) {
+			to.Set(rv.Convert(to.Type()))
+		}
+	} else if from.Kind() == reflect.Ptr {
+		return set(to, from.Elem(), deepCopy, converters)
+	} else {
+		return false, nil
+	}
+
+	return true, nil
+}
+
+// lookupAndCopyWithConverter looks up the type pair, on success the TypeConverter Fn func is called to copy src to dst field.
+func lookupAndCopyWithConverter(to, from reflect.Value, converters map[converterPair]TypeConverter) (copied bool, err error) {
+	pair := converterPair{
+		SrcType: from.Type(),
+		DstType: to.Type(),
+	}
+
+	if cnv, ok := converters[pair]; ok {
+		result, err := cnv.Fn(from.Interface())
+		if err != nil {
+			return false, err
+		}
+
+		if result != nil {
+			to.Set(reflect.ValueOf(result))
+		} else {
+			// in case we've got a nil value to copy
+			to.Set(reflect.Zero(to.Type()))
+		}
+
+		return true, nil
+	}
+
+	return false, nil
+}
+
+// parseTags Parses struct tags and returns uint8 bit flags.
+func parseTags(tag string) (flg uint8, name string, err error) {
+	for _, t := range strings.Split(tag, ",") {
+		switch t {
+		case "-":
+			flg = tagIgnore
+			return
+		case "must":
+			flg = flg | tagMust
+		case "nopanic":
+			flg = flg | tagNoPanic
+		default:
+			if unicode.IsUpper([]rune(t)[0]) {
+				name = strings.TrimSpace(t)
+			} else {
+				err = ErrFieldNameTagStartNotUpperCase
+			}
+		}
+	}
+	return
+}
+
+// getTagFlags Parses struct tags for bit flags, field name.
+func getFlags(dest, src reflect.Value, toType, fromType reflect.Type) (flags, error) {
+	flgs := flags{
+		BitFlags: map[string]uint8{},
+		SrcNames: tagNameMapping{
+			FieldNameToTag: map[string]string{},
+			TagToFieldName: map[string]string{},
+		},
+		DestNames: tagNameMapping{
+			FieldNameToTag: map[string]string{},
+			TagToFieldName: map[string]string{},
+		},
+	}
+	var toTypeFields, fromTypeFields []reflect.StructField
+	if dest.IsValid() {
+		toTypeFields = deepFields(toType)
+	}
+	if src.IsValid() {
+		fromTypeFields = deepFields(fromType)
+	}
+
+	// Get a list dest of tags
+	for _, field := range toTypeFields {
+		tags := field.Tag.Get("copier")
+		if tags != "" {
+			var name string
+			var err error
+			if flgs.BitFlags[field.Name], name, err = parseTags(tags); err != nil {
+				return flags{}, err
+			} else if name != "" {
+				flgs.DestNames.FieldNameToTag[field.Name] = name
+				flgs.DestNames.TagToFieldName[name] = field.Name
+			}
+		}
+	}
+
+	// Get a list source of tags
+	for _, field := range fromTypeFields {
+		tags := field.Tag.Get("copier")
+		if tags != "" {
+			var name string
+			var err error
+			if _, name, err = parseTags(tags); err != nil {
+				return flags{}, err
+			} else if name != "" {
+				flgs.SrcNames.FieldNameToTag[field.Name] = name
+				flgs.SrcNames.TagToFieldName[name] = field.Name
+			}
+		}
+	}
+	return flgs, nil
+}
+
+// checkBitFlags Checks flags for error or panic conditions.
+func checkBitFlags(flagsList map[string]uint8) (err error) {
+	// Check flag conditions were met
+	for name, flgs := range flagsList {
+		if flgs&hasCopied == 0 {
+			switch {
+			case flgs&tagMust != 0 && flgs&tagNoPanic != 0:
+				err = fmt.Errorf("field %s has must tag but was not copied", name)
+				return
+			case flgs&(tagMust) != 0:
+				panic(fmt.Sprintf("Field %s has must tag but was not copied", name))
+			}
+		}
+	}
+	return
+}
+
+func getFieldName(fieldName string, flgs flags, fieldNameMapping map[string]string) (srcFieldName string, destFieldName string) {
+	// get dest field name
+	if name, ok := fieldNameMapping[fieldName]; ok {
+		srcFieldName = fieldName
+		destFieldName = name
+		return
+	}
+
+	if srcTagName, ok := flgs.SrcNames.FieldNameToTag[fieldName]; ok {
+		destFieldName = srcTagName
+		if destTagName, ok := flgs.DestNames.TagToFieldName[srcTagName]; ok {
+			destFieldName = destTagName
+		}
+	} else {
+		if destTagName, ok := flgs.DestNames.TagToFieldName[fieldName]; ok {
+			destFieldName = destTagName
+		}
+	}
+	if destFieldName == "" {
+		destFieldName = fieldName
+	}
+
+	// get source field name
+	if destTagName, ok := flgs.DestNames.FieldNameToTag[fieldName]; ok {
+		srcFieldName = destTagName
+		if srcField, ok := flgs.SrcNames.TagToFieldName[destTagName]; ok {
+			srcFieldName = srcField
+		}
+	} else {
+		if srcField, ok := flgs.SrcNames.TagToFieldName[fieldName]; ok {
+			srcFieldName = srcField
+		}
+	}
+
+	if srcFieldName == "" {
+		srcFieldName = fieldName
+	}
+	return
+}
+
+func driverValuer(v reflect.Value) (i driver.Valuer, ok bool) {
+	if !v.CanAddr() {
+		i, ok = v.Interface().(driver.Valuer)
+		return
+	}
+
+	i, ok = v.Addr().Interface().(driver.Valuer)
+	return
+}
+
+func fieldByName(v reflect.Value, name string, caseSensitive bool) reflect.Value {
+	if caseSensitive {
+		return v.FieldByName(name)
+	}
+
+	return v.FieldByNameFunc(func(n string) bool { return strings.EqualFold(n, name) })
+}

+ 11 - 0
vendor/github.com/jinzhu/copier/errors.go

@@ -0,0 +1,11 @@
+package copier
+
+import "errors"
+
+var (
+	ErrInvalidCopyDestination        = errors.New("copy destination must be non-nil and addressable")
+	ErrInvalidCopyFrom               = errors.New("copy from must be non-nil and addressable")
+	ErrMapKeyNotMatch                = errors.New("map's key type doesn't match")
+	ErrNotSupported                  = errors.New("not supported")
+	ErrFieldNameTagStartNotUpperCase = errors.New("copier field name tag must be start upper case")
+)

+ 3 - 0
vendor/modules.txt

@@ -99,6 +99,9 @@ github.com/google/uuid
 github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule
 github.com/grpc-ecosystem/grpc-gateway/v2/runtime
 github.com/grpc-ecosystem/grpc-gateway/v2/utilities
+# github.com/jinzhu/copier v0.4.0
+## explicit; go 1.13
+github.com/jinzhu/copier
 # github.com/josharian/intern v1.0.0
 ## explicit; go 1.5
 github.com/josharian/intern

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff