jiangshuai
2023-11-08 8d090fa81fc1082ab09d5dd557756ec0c6d3b269
附件上传接口,交互文件服务器,缩略图制作
7个文件已添加
7个文件已修改
1510 ■■■■■ 已修改文件
conf/config.go 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
conf/config.yaml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controllers/reorder_rule_controller.go 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/docs.go 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
go.mod 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
go.sum 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main.go 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
proto/inventory_order.proto 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
proto/inventory_order/inventory_order.pb.go 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
proto/inventory_order/inventory_order_grpc.pb.go 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
proto/product_inventory.proto 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
proto/product_inventory/product_inventory.pb.go 672 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
proto/product_inventory/product_inventory_grpc.pb.go 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
proto/product_inventory/server.go 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
conf/config.go
@@ -30,6 +30,7 @@
        JWTSecret  string
        FileServer string //文件服务器地址
        ServerId   string //服务ID
        GrpcPort   string //grpc端口号
    }
    localConf struct {
conf/config.yaml
@@ -1,5 +1,6 @@
web:
  port: 8005
  grpcPort: 8006
  host: 192.168.20.119
  nodeId: wangpengfei
  ossType: local
@@ -22,3 +23,5 @@
  encoder: console
local:
  storePath: uploads/file
grpcServer:
  apsAddr: 192.168.20.119:9091
controllers/reorder_rule_controller.go
@@ -3,15 +3,20 @@
import (
    "github.com/gin-gonic/gin"
    "github.com/shopspring/decimal"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    "gorm.io/gorm"
    "strconv"
    "strings"
    "time"
    "wms/conf"
    "wms/constvar"
    "wms/extend/code"
    "wms/extend/util"
    "wms/models"
    "wms/pkg/logx"
    "wms/pkg/timex"
    "wms/proto/inventory_order"
    "wms/request"
)
@@ -254,6 +259,23 @@
    util.ResponseFormat(c, code.Success, "更新成功")
}
var InventoryOrderServiceConn *grpc.ClientConn
func InitInventoryOrderServiceConn() {
    var err error
    InventoryOrderServiceConn, err = grpc.Dial(conf.GrpcServerConf.ApsAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
    if err != nil {
        logx.Errorf("grpc dial product service error: %v", err.Error())
        return
    }
}
func CloseInventoryOrderServiceConn() {
    if InventoryOrderServiceConn != nil {
        InventoryOrderServiceConn.Close()
    }
}
// OrderAgain
// @Tags      重订货规则
// @Summary   再订一次
@@ -265,6 +287,17 @@
    var params models.ReorderRule
    if err := c.BindJSON(&params); err != nil {
        util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误")
        return
    }
    client := inventory_order.NewInventoryOrderServiceClient(InventoryOrderServiceConn)
    order, err := client.CreateNewOrder(c, &inventory_order.CreateNewOrderRequest{
        OrderNumber: params.OrderNumber.IntPart(),
        Unit:        params.Unit,
        ProductId:   params.ProductId,
        Customer:    "WMS推送",
    })
    if err != nil {
        util.ResponseFormat(c, code.RequestParamError, "grpc调用失败")
        return
    }
    location, err := models.NewLocationSearch().SetID(params.LocationId).First()
@@ -294,13 +327,14 @@
    operation.FromLocationID = 1
    operation.Number = strconv.FormatInt(time.Now().Unix(), 10)
    operation.ToLocationID = params.LocationId
    operation.SourceNumber = order.OrderId
    err = models.WithTransaction(func(db *gorm.DB) error {
        if err = models.NewOperationSearch().SetOrm(db).Create(&operation); err != nil {
            return err
        }
        params.OrderNumber = decimal.NewFromInt(0)
        err = models.NewReorderRuleSearch().SetID(params.Id).Update(&params)
        err = models.NewReorderRuleSearch().SetOrm(db).SetID(params.Id).Update(&params)
        return err
    })
    if err != nil {
docs/docs.go
@@ -4138,6 +4138,8 @@
    Description:      "",
    InfoInstanceName: "swagger",
    SwaggerTemplate:  docTemplate,
    LeftDelim:        "{{",
    RightDelim:       "}}",
}
func init() {
go.mod
@@ -19,7 +19,9 @@
    github.com/swaggo/swag v1.16.1
    go.uber.org/zap v1.24.0
    golang.org/x/crypto v0.13.0
    google.golang.org/genproto v0.0.0-20230323212658-478b75c54725
    google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98
    google.golang.org/grpc v1.58.2
    google.golang.org/protobuf v1.31.0
    gopkg.in/natefinch/lumberjack.v2 v2.2.1
    gorm.io/driver/mysql v1.5.0
    gorm.io/gorm v1.25.0
@@ -98,7 +100,7 @@
    golang.org/x/sys v0.12.0 // indirect
    golang.org/x/text v0.13.0 // indirect
    golang.org/x/tools v0.11.0 // indirect
    google.golang.org/protobuf v1.31.0 // indirect
    google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
    gopkg.in/ini.v1 v1.67.0 // indirect
    gopkg.in/yaml.v2 v2.4.0 // indirect
    gopkg.in/yaml.v3 v3.0.1 // indirect
go.sum
@@ -667,8 +667,11 @@
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20230323212658-478b75c54725 h1:VmCWItVXcKboEMCwZaWge+1JLiTCQSngZeINF+wzO+g=
google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g=
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0=
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -686,6 +689,7 @@
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I=
google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
main.go
@@ -2,14 +2,19 @@
import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "net"
    "net/http"
    "os"
    "os/signal"
    "syscall"
    "time"
    "wms/conf"
    "wms/controllers"
    "wms/models"
    "wms/pkg/logx"
    "wms/proto/product_inventory"
    "wms/router"
)
@@ -38,6 +43,25 @@
        WriteTimeout: 5 * time.Second,
    }
    go shutdown(server)
    //启动grpc客户端
    go controllers.InitInventoryOrderServiceConn()
    //启动grpc服务
    go func() {
        ln, err := net.Listen("tcp", ":"+conf.WebConf.GrpcPort)
        if err != nil {
            logx.Errorf("grpc server init error: %v", err.Error())
            panic(fmt.Sprintf("grpc server init error: %v", err.Error()))
        }
        fmt.Println("-----------监听端口: ", conf.WebConf.GrpcPort)
        s := grpc.NewServer()
        //todo 添加具体服务
        product_inventory.RegisterProductInventoryServiceServer(s, &product_inventory.Server{})
        err = s.Serve(ln)
        if err != nil {
            logx.Errorf("grpc server init error: %v", err.Error())
            panic(fmt.Sprintf("grpc server init error: %v", err.Error()))
        }
    }()
    logx.Error(server.ListenAndServe().Error())
}
@@ -51,6 +75,7 @@
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    controllers.CloseInventoryOrderServiceConn()
    // 关闭HTTP服务器
    if err := server.Shutdown(ctx); err != nil {
        logx.Infof("服务优雅退出失败: %v", err)
proto/inventory_order.proto
New file
@@ -0,0 +1,20 @@
syntax = "proto3";
option go_package = "./inventory_order";
service inventoryOrderService {
  rpc CreateNewOrder(CreateNewOrderRequest) returns(CreateNewOrderResponse) {}
}
message CreateNewOrderRequest{
  int64 OrderNumber = 1;//订购数量
  string Unit = 2;//单位
  string ProductId = 3;
  string Customer = 4;//客户编码
}
message CreateNewOrderResponse{
  int32   Code = 1;
  string  Msg = 2;
  string OrderId = 3;
}
proto/inventory_order/inventory_order.pb.go
New file
@@ -0,0 +1,262 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
//     protoc-gen-go v1.26.0
//     protoc        v4.24.0
// source: inventory_order.proto
package inventory_order
import (
    protoreflect "google.golang.org/protobuf/reflect/protoreflect"
    protoimpl "google.golang.org/protobuf/runtime/protoimpl"
    reflect "reflect"
    sync "sync"
)
const (
    // Verify that this generated code is sufficiently up-to-date.
    _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
    // Verify that runtime/protoimpl is sufficiently up-to-date.
    _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type CreateNewOrderRequest struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields
    OrderNumber int64  `protobuf:"varint,1,opt,name=OrderNumber,proto3" json:"OrderNumber,omitempty"` //订购数量
    Unit        string `protobuf:"bytes,2,opt,name=Unit,proto3" json:"Unit,omitempty"`                //单位
    ProductId   string `protobuf:"bytes,3,opt,name=ProductId,proto3" json:"ProductId,omitempty"`
    Customer    string `protobuf:"bytes,4,opt,name=Customer,proto3" json:"Customer,omitempty"` //客户编码
}
func (x *CreateNewOrderRequest) Reset() {
    *x = CreateNewOrderRequest{}
    if protoimpl.UnsafeEnabled {
        mi := &file_inventory_order_proto_msgTypes[0]
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        ms.StoreMessageInfo(mi)
    }
}
func (x *CreateNewOrderRequest) String() string {
    return protoimpl.X.MessageStringOf(x)
}
func (*CreateNewOrderRequest) ProtoMessage() {}
func (x *CreateNewOrderRequest) ProtoReflect() protoreflect.Message {
    mi := &file_inventory_order_proto_msgTypes[0]
    if protoimpl.UnsafeEnabled && x != nil {
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        if ms.LoadMessageInfo() == nil {
            ms.StoreMessageInfo(mi)
        }
        return ms
    }
    return mi.MessageOf(x)
}
// Deprecated: Use CreateNewOrderRequest.ProtoReflect.Descriptor instead.
func (*CreateNewOrderRequest) Descriptor() ([]byte, []int) {
    return file_inventory_order_proto_rawDescGZIP(), []int{0}
}
func (x *CreateNewOrderRequest) GetOrderNumber() int64 {
    if x != nil {
        return x.OrderNumber
    }
    return 0
}
func (x *CreateNewOrderRequest) GetUnit() string {
    if x != nil {
        return x.Unit
    }
    return ""
}
func (x *CreateNewOrderRequest) GetProductId() string {
    if x != nil {
        return x.ProductId
    }
    return ""
}
func (x *CreateNewOrderRequest) GetCustomer() string {
    if x != nil {
        return x.Customer
    }
    return ""
}
type CreateNewOrderResponse struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields
    Code    int32  `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
    Msg     string `protobuf:"bytes,2,opt,name=Msg,proto3" json:"Msg,omitempty"`
    OrderId string `protobuf:"bytes,3,opt,name=OrderId,proto3" json:"OrderId,omitempty"`
}
func (x *CreateNewOrderResponse) Reset() {
    *x = CreateNewOrderResponse{}
    if protoimpl.UnsafeEnabled {
        mi := &file_inventory_order_proto_msgTypes[1]
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        ms.StoreMessageInfo(mi)
    }
}
func (x *CreateNewOrderResponse) String() string {
    return protoimpl.X.MessageStringOf(x)
}
func (*CreateNewOrderResponse) ProtoMessage() {}
func (x *CreateNewOrderResponse) ProtoReflect() protoreflect.Message {
    mi := &file_inventory_order_proto_msgTypes[1]
    if protoimpl.UnsafeEnabled && x != nil {
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        if ms.LoadMessageInfo() == nil {
            ms.StoreMessageInfo(mi)
        }
        return ms
    }
    return mi.MessageOf(x)
}
// Deprecated: Use CreateNewOrderResponse.ProtoReflect.Descriptor instead.
func (*CreateNewOrderResponse) Descriptor() ([]byte, []int) {
    return file_inventory_order_proto_rawDescGZIP(), []int{1}
}
func (x *CreateNewOrderResponse) GetCode() int32 {
    if x != nil {
        return x.Code
    }
    return 0
}
func (x *CreateNewOrderResponse) GetMsg() string {
    if x != nil {
        return x.Msg
    }
    return ""
}
func (x *CreateNewOrderResponse) GetOrderId() string {
    if x != nil {
        return x.OrderId
    }
    return ""
}
var File_inventory_order_proto protoreflect.FileDescriptor
var file_inventory_order_proto_rawDesc = []byte{
    0x0a, 0x15, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6f, 0x72, 0x64, 0x65,
    0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x87, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61,
    0x74, 0x65, 0x4e, 0x65, 0x77, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
    0x74, 0x12, 0x20, 0x0a, 0x0b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72,
    0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d,
    0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x55, 0x6e, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
    0x09, 0x52, 0x04, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x64, 0x75,
    0x63, 0x74, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x64,
    0x75, 0x63, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65,
    0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65,
    0x72, 0x22, 0x58, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x4f, 0x72,
    0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x43,
    0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12,
    0x10, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4d, 0x73,
    0x67, 0x12, 0x18, 0x0a, 0x07, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01,
    0x28, 0x09, 0x52, 0x07, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x32, 0x5c, 0x0a, 0x15, 0x69,
    0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x65, 0x72,
    0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65,
    0x77, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x16, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e,
    0x65, 0x77, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17,
    0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52,
    0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x13, 0x5a, 0x11, 0x2e, 0x2f, 0x69,
    0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x06,
    0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
    file_inventory_order_proto_rawDescOnce sync.Once
    file_inventory_order_proto_rawDescData = file_inventory_order_proto_rawDesc
)
func file_inventory_order_proto_rawDescGZIP() []byte {
    file_inventory_order_proto_rawDescOnce.Do(func() {
        file_inventory_order_proto_rawDescData = protoimpl.X.CompressGZIP(file_inventory_order_proto_rawDescData)
    })
    return file_inventory_order_proto_rawDescData
}
var file_inventory_order_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_inventory_order_proto_goTypes = []interface{}{
    (*CreateNewOrderRequest)(nil),  // 0: CreateNewOrderRequest
    (*CreateNewOrderResponse)(nil), // 1: CreateNewOrderResponse
}
var file_inventory_order_proto_depIdxs = []int32{
    0, // 0: inventoryOrderService.CreateNewOrder:input_type -> CreateNewOrderRequest
    1, // 1: inventoryOrderService.CreateNewOrder:output_type -> CreateNewOrderResponse
    1, // [1:2] is the sub-list for method output_type
    0, // [0:1] is the sub-list for method input_type
    0, // [0:0] is the sub-list for extension type_name
    0, // [0:0] is the sub-list for extension extendee
    0, // [0:0] is the sub-list for field type_name
}
func init() { file_inventory_order_proto_init() }
func file_inventory_order_proto_init() {
    if File_inventory_order_proto != nil {
        return
    }
    if !protoimpl.UnsafeEnabled {
        file_inventory_order_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
            switch v := v.(*CreateNewOrderRequest); i {
            case 0:
                return &v.state
            case 1:
                return &v.sizeCache
            case 2:
                return &v.unknownFields
            default:
                return nil
            }
        }
        file_inventory_order_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
            switch v := v.(*CreateNewOrderResponse); i {
            case 0:
                return &v.state
            case 1:
                return &v.sizeCache
            case 2:
                return &v.unknownFields
            default:
                return nil
            }
        }
    }
    type x struct{}
    out := protoimpl.TypeBuilder{
        File: protoimpl.DescBuilder{
            GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
            RawDescriptor: file_inventory_order_proto_rawDesc,
            NumEnums:      0,
            NumMessages:   2,
            NumExtensions: 0,
            NumServices:   1,
        },
        GoTypes:           file_inventory_order_proto_goTypes,
        DependencyIndexes: file_inventory_order_proto_depIdxs,
        MessageInfos:      file_inventory_order_proto_msgTypes,
    }.Build()
    File_inventory_order_proto = out.File
    file_inventory_order_proto_rawDesc = nil
    file_inventory_order_proto_goTypes = nil
    file_inventory_order_proto_depIdxs = nil
}
proto/inventory_order/inventory_order_grpc.pb.go
New file
@@ -0,0 +1,101 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package inventory_order
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
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// InventoryOrderServiceClient is the client API for InventoryOrderService 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 InventoryOrderServiceClient interface {
    CreateNewOrder(ctx context.Context, in *CreateNewOrderRequest, opts ...grpc.CallOption) (*CreateNewOrderResponse, error)
}
type inventoryOrderServiceClient struct {
    cc grpc.ClientConnInterface
}
func NewInventoryOrderServiceClient(cc grpc.ClientConnInterface) InventoryOrderServiceClient {
    return &inventoryOrderServiceClient{cc}
}
func (c *inventoryOrderServiceClient) CreateNewOrder(ctx context.Context, in *CreateNewOrderRequest, opts ...grpc.CallOption) (*CreateNewOrderResponse, error) {
    out := new(CreateNewOrderResponse)
    err := c.cc.Invoke(ctx, "/inventoryOrderService/CreateNewOrder", in, out, opts...)
    if err != nil {
        return nil, err
    }
    return out, nil
}
// InventoryOrderServiceServer is the server API for InventoryOrderService service.
// All implementations must embed UnimplementedInventoryOrderServiceServer
// for forward compatibility
type InventoryOrderServiceServer interface {
    CreateNewOrder(context.Context, *CreateNewOrderRequest) (*CreateNewOrderResponse, error)
    mustEmbedUnimplementedInventoryOrderServiceServer()
}
// UnimplementedInventoryOrderServiceServer must be embedded to have forward compatible implementations.
type UnimplementedInventoryOrderServiceServer struct {
}
func (UnimplementedInventoryOrderServiceServer) CreateNewOrder(context.Context, *CreateNewOrderRequest) (*CreateNewOrderResponse, error) {
    return nil, status.Errorf(codes.Unimplemented, "method CreateNewOrder not implemented")
}
func (UnimplementedInventoryOrderServiceServer) mustEmbedUnimplementedInventoryOrderServiceServer() {}
// UnsafeInventoryOrderServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to InventoryOrderServiceServer will
// result in compilation errors.
type UnsafeInventoryOrderServiceServer interface {
    mustEmbedUnimplementedInventoryOrderServiceServer()
}
func RegisterInventoryOrderServiceServer(s grpc.ServiceRegistrar, srv InventoryOrderServiceServer) {
    s.RegisterService(&InventoryOrderService_ServiceDesc, srv)
}
func _InventoryOrderService_CreateNewOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
    in := new(CreateNewOrderRequest)
    if err := dec(in); err != nil {
        return nil, err
    }
    if interceptor == nil {
        return srv.(InventoryOrderServiceServer).CreateNewOrder(ctx, in)
    }
    info := &grpc.UnaryServerInfo{
        Server:     srv,
        FullMethod: "/inventoryOrderService/CreateNewOrder",
    }
    handler := func(ctx context.Context, req interface{}) (interface{}, error) {
        return srv.(InventoryOrderServiceServer).CreateNewOrder(ctx, req.(*CreateNewOrderRequest))
    }
    return interceptor(ctx, in, info, handler)
}
// InventoryOrderService_ServiceDesc is the grpc.ServiceDesc for InventoryOrderService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var InventoryOrderService_ServiceDesc = grpc.ServiceDesc{
    ServiceName: "inventoryOrderService",
    HandlerType: (*InventoryOrderServiceServer)(nil),
    Methods: []grpc.MethodDesc{
        {
            MethodName: "CreateNewOrder",
            Handler:    _InventoryOrderService_CreateNewOrder_Handler,
        },
    },
    Streams:  []grpc.StreamDesc{},
    Metadata: "inventory_order.proto",
}
proto/product_inventory.proto
New file
@@ -0,0 +1,54 @@
syntax = "proto3";
option go_package = "./product_inventory";
service productInventoryService {
  rpc CreateOperation(CreateOperationRequest) returns(CreateOperationResponse) {}
  rpc GetInventoryProductInfo(GetInventoryProductInfoRequest) returns (GetInventoryProductInfoResponse) {}
}
message CreateOperationRequest{
  string Number = 1;//明细单编码
  string Addressee = 2;//收货人
  string Address = 3;//收货地址
  string Phone = 4;
  int32 DeliverType = 5;//交付类型
  repeated InventoryProduct ProductList = 6;
}
message InventoryProduct{
  string Id = 1;
  string Amount = 2;
}
message CreateOperationResponse{
  int32   Code = 1;
  string  Msg = 2;
}
//-------------------------------------------------------
message GetInventoryProductInfoRequest {
  string Number = 1;//明细单编码
}
message ProductInfo{
  string Id = 1;
  string Name = 2;
  string OrderAmount = 3;//订单数量
  string Unit = 4;
  string Invoice = 5;//发货单
  string Carrier = 6;//承运商
  string Waybill = 7;//运单号
  string SalePrice = 8;//销售单价
  string Valorem = 9;//价税合计
  string Warehouse = 10;
  string Amount = 11;//在库数量
  string AvailableNumber = 12;//可用库存
}
message GetInventoryProductInfoResponse{
  int32   Code = 1;
  string  Msg = 2;
  repeated ProductInfo ProductList = 3;
}
proto/product_inventory/product_inventory.pb.go
New file
@@ -0,0 +1,672 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
//     protoc-gen-go v1.26.0
//     protoc        v4.24.0
// source: product_inventory.proto
package product_inventory
import (
    protoreflect "google.golang.org/protobuf/reflect/protoreflect"
    protoimpl "google.golang.org/protobuf/runtime/protoimpl"
    reflect "reflect"
    sync "sync"
)
const (
    // Verify that this generated code is sufficiently up-to-date.
    _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
    // Verify that runtime/protoimpl is sufficiently up-to-date.
    _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type CreateOperationRequest struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields
    Number      string              `protobuf:"bytes,1,opt,name=Number,proto3" json:"Number,omitempty"`       //明细单编码
    Addressee   string              `protobuf:"bytes,2,opt,name=Addressee,proto3" json:"Addressee,omitempty"` //收货人
    Address     string              `protobuf:"bytes,3,opt,name=Address,proto3" json:"Address,omitempty"`     //收货地址
    Phone       string              `protobuf:"bytes,4,opt,name=Phone,proto3" json:"Phone,omitempty"`
    DeliverType int32               `protobuf:"varint,5,opt,name=DeliverType,proto3" json:"DeliverType,omitempty"` //交付类型
    ProductList []*InventoryProduct `protobuf:"bytes,6,rep,name=ProductList,proto3" json:"ProductList,omitempty"`
}
func (x *CreateOperationRequest) Reset() {
    *x = CreateOperationRequest{}
    if protoimpl.UnsafeEnabled {
        mi := &file_product_inventory_proto_msgTypes[0]
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        ms.StoreMessageInfo(mi)
    }
}
func (x *CreateOperationRequest) String() string {
    return protoimpl.X.MessageStringOf(x)
}
func (*CreateOperationRequest) ProtoMessage() {}
func (x *CreateOperationRequest) ProtoReflect() protoreflect.Message {
    mi := &file_product_inventory_proto_msgTypes[0]
    if protoimpl.UnsafeEnabled && x != nil {
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        if ms.LoadMessageInfo() == nil {
            ms.StoreMessageInfo(mi)
        }
        return ms
    }
    return mi.MessageOf(x)
}
// Deprecated: Use CreateOperationRequest.ProtoReflect.Descriptor instead.
func (*CreateOperationRequest) Descriptor() ([]byte, []int) {
    return file_product_inventory_proto_rawDescGZIP(), []int{0}
}
func (x *CreateOperationRequest) GetNumber() string {
    if x != nil {
        return x.Number
    }
    return ""
}
func (x *CreateOperationRequest) GetAddressee() string {
    if x != nil {
        return x.Addressee
    }
    return ""
}
func (x *CreateOperationRequest) GetAddress() string {
    if x != nil {
        return x.Address
    }
    return ""
}
func (x *CreateOperationRequest) GetPhone() string {
    if x != nil {
        return x.Phone
    }
    return ""
}
func (x *CreateOperationRequest) GetDeliverType() int32 {
    if x != nil {
        return x.DeliverType
    }
    return 0
}
func (x *CreateOperationRequest) GetProductList() []*InventoryProduct {
    if x != nil {
        return x.ProductList
    }
    return nil
}
type InventoryProduct struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields
    Id     string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"`
    Amount string `protobuf:"bytes,2,opt,name=Amount,proto3" json:"Amount,omitempty"`
}
func (x *InventoryProduct) Reset() {
    *x = InventoryProduct{}
    if protoimpl.UnsafeEnabled {
        mi := &file_product_inventory_proto_msgTypes[1]
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        ms.StoreMessageInfo(mi)
    }
}
func (x *InventoryProduct) String() string {
    return protoimpl.X.MessageStringOf(x)
}
func (*InventoryProduct) ProtoMessage() {}
func (x *InventoryProduct) ProtoReflect() protoreflect.Message {
    mi := &file_product_inventory_proto_msgTypes[1]
    if protoimpl.UnsafeEnabled && x != nil {
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        if ms.LoadMessageInfo() == nil {
            ms.StoreMessageInfo(mi)
        }
        return ms
    }
    return mi.MessageOf(x)
}
// Deprecated: Use InventoryProduct.ProtoReflect.Descriptor instead.
func (*InventoryProduct) Descriptor() ([]byte, []int) {
    return file_product_inventory_proto_rawDescGZIP(), []int{1}
}
func (x *InventoryProduct) GetId() string {
    if x != nil {
        return x.Id
    }
    return ""
}
func (x *InventoryProduct) GetAmount() string {
    if x != nil {
        return x.Amount
    }
    return ""
}
type CreateOperationResponse struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields
    Code int32  `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
    Msg  string `protobuf:"bytes,2,opt,name=Msg,proto3" json:"Msg,omitempty"`
}
func (x *CreateOperationResponse) Reset() {
    *x = CreateOperationResponse{}
    if protoimpl.UnsafeEnabled {
        mi := &file_product_inventory_proto_msgTypes[2]
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        ms.StoreMessageInfo(mi)
    }
}
func (x *CreateOperationResponse) String() string {
    return protoimpl.X.MessageStringOf(x)
}
func (*CreateOperationResponse) ProtoMessage() {}
func (x *CreateOperationResponse) ProtoReflect() protoreflect.Message {
    mi := &file_product_inventory_proto_msgTypes[2]
    if protoimpl.UnsafeEnabled && x != nil {
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        if ms.LoadMessageInfo() == nil {
            ms.StoreMessageInfo(mi)
        }
        return ms
    }
    return mi.MessageOf(x)
}
// Deprecated: Use CreateOperationResponse.ProtoReflect.Descriptor instead.
func (*CreateOperationResponse) Descriptor() ([]byte, []int) {
    return file_product_inventory_proto_rawDescGZIP(), []int{2}
}
func (x *CreateOperationResponse) GetCode() int32 {
    if x != nil {
        return x.Code
    }
    return 0
}
func (x *CreateOperationResponse) GetMsg() string {
    if x != nil {
        return x.Msg
    }
    return ""
}
type GetInventoryProductInfoRequest struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields
    Number string `protobuf:"bytes,1,opt,name=Number,proto3" json:"Number,omitempty"` //明细单编码
}
func (x *GetInventoryProductInfoRequest) Reset() {
    *x = GetInventoryProductInfoRequest{}
    if protoimpl.UnsafeEnabled {
        mi := &file_product_inventory_proto_msgTypes[3]
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        ms.StoreMessageInfo(mi)
    }
}
func (x *GetInventoryProductInfoRequest) String() string {
    return protoimpl.X.MessageStringOf(x)
}
func (*GetInventoryProductInfoRequest) ProtoMessage() {}
func (x *GetInventoryProductInfoRequest) ProtoReflect() protoreflect.Message {
    mi := &file_product_inventory_proto_msgTypes[3]
    if protoimpl.UnsafeEnabled && x != nil {
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        if ms.LoadMessageInfo() == nil {
            ms.StoreMessageInfo(mi)
        }
        return ms
    }
    return mi.MessageOf(x)
}
// Deprecated: Use GetInventoryProductInfoRequest.ProtoReflect.Descriptor instead.
func (*GetInventoryProductInfoRequest) Descriptor() ([]byte, []int) {
    return file_product_inventory_proto_rawDescGZIP(), []int{3}
}
func (x *GetInventoryProductInfoRequest) GetNumber() string {
    if x != nil {
        return x.Number
    }
    return ""
}
type ProductInfo struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields
    Id              string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"`
    Name            string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
    OrderAmount     string `protobuf:"bytes,3,opt,name=OrderAmount,proto3" json:"OrderAmount,omitempty"` //订单数量
    Unit            string `protobuf:"bytes,4,opt,name=Unit,proto3" json:"Unit,omitempty"`
    Invoice         string `protobuf:"bytes,5,opt,name=Invoice,proto3" json:"Invoice,omitempty"`     //发货单
    Carrier         string `protobuf:"bytes,6,opt,name=Carrier,proto3" json:"Carrier,omitempty"`     //承运商
    Waybill         string `protobuf:"bytes,7,opt,name=Waybill,proto3" json:"Waybill,omitempty"`     //运单号
    SalePrice       string `protobuf:"bytes,8,opt,name=SalePrice,proto3" json:"SalePrice,omitempty"` //销售单价
    Valorem         string `protobuf:"bytes,9,opt,name=Valorem,proto3" json:"Valorem,omitempty"`     //价税合计
    Warehouse       string `protobuf:"bytes,10,opt,name=Warehouse,proto3" json:"Warehouse,omitempty"`
    Amount          string `protobuf:"bytes,11,opt,name=Amount,proto3" json:"Amount,omitempty"`                   //在库数量
    AvailableNumber string `protobuf:"bytes,12,opt,name=AvailableNumber,proto3" json:"AvailableNumber,omitempty"` //可用库存
}
func (x *ProductInfo) Reset() {
    *x = ProductInfo{}
    if protoimpl.UnsafeEnabled {
        mi := &file_product_inventory_proto_msgTypes[4]
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        ms.StoreMessageInfo(mi)
    }
}
func (x *ProductInfo) String() string {
    return protoimpl.X.MessageStringOf(x)
}
func (*ProductInfo) ProtoMessage() {}
func (x *ProductInfo) ProtoReflect() protoreflect.Message {
    mi := &file_product_inventory_proto_msgTypes[4]
    if protoimpl.UnsafeEnabled && x != nil {
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        if ms.LoadMessageInfo() == nil {
            ms.StoreMessageInfo(mi)
        }
        return ms
    }
    return mi.MessageOf(x)
}
// Deprecated: Use ProductInfo.ProtoReflect.Descriptor instead.
func (*ProductInfo) Descriptor() ([]byte, []int) {
    return file_product_inventory_proto_rawDescGZIP(), []int{4}
}
func (x *ProductInfo) GetId() string {
    if x != nil {
        return x.Id
    }
    return ""
}
func (x *ProductInfo) GetName() string {
    if x != nil {
        return x.Name
    }
    return ""
}
func (x *ProductInfo) GetOrderAmount() string {
    if x != nil {
        return x.OrderAmount
    }
    return ""
}
func (x *ProductInfo) GetUnit() string {
    if x != nil {
        return x.Unit
    }
    return ""
}
func (x *ProductInfo) GetInvoice() string {
    if x != nil {
        return x.Invoice
    }
    return ""
}
func (x *ProductInfo) GetCarrier() string {
    if x != nil {
        return x.Carrier
    }
    return ""
}
func (x *ProductInfo) GetWaybill() string {
    if x != nil {
        return x.Waybill
    }
    return ""
}
func (x *ProductInfo) GetSalePrice() string {
    if x != nil {
        return x.SalePrice
    }
    return ""
}
func (x *ProductInfo) GetValorem() string {
    if x != nil {
        return x.Valorem
    }
    return ""
}
func (x *ProductInfo) GetWarehouse() string {
    if x != nil {
        return x.Warehouse
    }
    return ""
}
func (x *ProductInfo) GetAmount() string {
    if x != nil {
        return x.Amount
    }
    return ""
}
func (x *ProductInfo) GetAvailableNumber() string {
    if x != nil {
        return x.AvailableNumber
    }
    return ""
}
type GetInventoryProductInfoResponse struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields
    Code        int32          `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
    Msg         string         `protobuf:"bytes,2,opt,name=Msg,proto3" json:"Msg,omitempty"`
    ProductList []*ProductInfo `protobuf:"bytes,3,rep,name=ProductList,proto3" json:"ProductList,omitempty"`
}
func (x *GetInventoryProductInfoResponse) Reset() {
    *x = GetInventoryProductInfoResponse{}
    if protoimpl.UnsafeEnabled {
        mi := &file_product_inventory_proto_msgTypes[5]
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        ms.StoreMessageInfo(mi)
    }
}
func (x *GetInventoryProductInfoResponse) String() string {
    return protoimpl.X.MessageStringOf(x)
}
func (*GetInventoryProductInfoResponse) ProtoMessage() {}
func (x *GetInventoryProductInfoResponse) ProtoReflect() protoreflect.Message {
    mi := &file_product_inventory_proto_msgTypes[5]
    if protoimpl.UnsafeEnabled && x != nil {
        ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
        if ms.LoadMessageInfo() == nil {
            ms.StoreMessageInfo(mi)
        }
        return ms
    }
    return mi.MessageOf(x)
}
// Deprecated: Use GetInventoryProductInfoResponse.ProtoReflect.Descriptor instead.
func (*GetInventoryProductInfoResponse) Descriptor() ([]byte, []int) {
    return file_product_inventory_proto_rawDescGZIP(), []int{5}
}
func (x *GetInventoryProductInfoResponse) GetCode() int32 {
    if x != nil {
        return x.Code
    }
    return 0
}
func (x *GetInventoryProductInfoResponse) GetMsg() string {
    if x != nil {
        return x.Msg
    }
    return ""
}
func (x *GetInventoryProductInfoResponse) GetProductList() []*ProductInfo {
    if x != nil {
        return x.ProductList
    }
    return nil
}
var File_product_inventory_proto protoreflect.FileDescriptor
var file_product_inventory_proto_rawDesc = []byte{
    0x0a, 0x17, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74,
    0x6f, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd5, 0x01, 0x0a, 0x16, 0x43, 0x72,
    0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71,
    0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01,
    0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09,
    0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
    0x09, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x41, 0x64,
    0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x41, 0x64, 0x64,
    0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x04, 0x20,
    0x01, 0x28, 0x09, 0x52, 0x05, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65,
    0x6c, 0x69, 0x76, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
    0x0b, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x33, 0x0a, 0x0b,
    0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x06, 0x20, 0x03, 0x28,
    0x0b, 0x32, 0x11, 0x2e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x72, 0x6f,
    0x64, 0x75, 0x63, 0x74, 0x52, 0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73,
    0x74, 0x22, 0x3a, 0x0a, 0x10, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x72,
    0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
    0x09, 0x52, 0x02, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18,
    0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3f, 0x0a,
    0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
    0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65,
    0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03,
    0x4d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4d, 0x73, 0x67, 0x22, 0x38,
    0x0a, 0x1e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x72,
    0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
    0x12, 0x16, 0x0a, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
    0x52, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xcd, 0x02, 0x0a, 0x0b, 0x50, 0x72, 0x6f,
    0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01,
    0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65,
    0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b,
    0x4f, 0x72, 0x64, 0x65, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
    0x09, 0x52, 0x0b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12,
    0x0a, 0x04, 0x55, 0x6e, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x6e,
    0x69, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x18, 0x05, 0x20,
    0x01, 0x28, 0x09, 0x52, 0x07, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07,
    0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x43,
    0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x57, 0x61, 0x79, 0x62, 0x69, 0x6c,
    0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x57, 0x61, 0x79, 0x62, 0x69, 0x6c, 0x6c,
    0x12, 0x1c, 0x0a, 0x09, 0x53, 0x61, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x63, 0x65, 0x18, 0x08, 0x20,
    0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x61, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x18,
    0x0a, 0x07, 0x56, 0x61, 0x6c, 0x6f, 0x72, 0x65, 0x6d, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52,
    0x07, 0x56, 0x61, 0x6c, 0x6f, 0x72, 0x65, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x57, 0x61, 0x72, 0x65,
    0x68, 0x6f, 0x75, 0x73, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x57, 0x61, 0x72,
    0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
    0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28,
    0x0a, 0x0f, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65,
    0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
    0x6c, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x77, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x49,
    0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49,
    0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x43,
    0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12,
    0x10, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4d, 0x73,
    0x67, 0x12, 0x2e, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74,
    0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74,
    0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73,
    0x74, 0x32, 0xc1, 0x01, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x76,
    0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x46, 0x0a,
    0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
    0x12, 0x17, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69,
    0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x43, 0x72, 0x65, 0x61,
    0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
    0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x65,
    0x6e, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f,
    0x12, 0x1f, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x50,
    0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
    0x74, 0x1a, 0x20, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79,
    0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f,
    0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x15, 0x5a, 0x13, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x64, 0x75,
    0x63, 0x74, 0x5f, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72,
    0x6f, 0x74, 0x6f, 0x33,
}
var (
    file_product_inventory_proto_rawDescOnce sync.Once
    file_product_inventory_proto_rawDescData = file_product_inventory_proto_rawDesc
)
func file_product_inventory_proto_rawDescGZIP() []byte {
    file_product_inventory_proto_rawDescOnce.Do(func() {
        file_product_inventory_proto_rawDescData = protoimpl.X.CompressGZIP(file_product_inventory_proto_rawDescData)
    })
    return file_product_inventory_proto_rawDescData
}
var file_product_inventory_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_product_inventory_proto_goTypes = []interface{}{
    (*CreateOperationRequest)(nil),          // 0: CreateOperationRequest
    (*InventoryProduct)(nil),                // 1: InventoryProduct
    (*CreateOperationResponse)(nil),         // 2: CreateOperationResponse
    (*GetInventoryProductInfoRequest)(nil),  // 3: GetInventoryProductInfoRequest
    (*ProductInfo)(nil),                     // 4: ProductInfo
    (*GetInventoryProductInfoResponse)(nil), // 5: GetInventoryProductInfoResponse
}
var file_product_inventory_proto_depIdxs = []int32{
    1, // 0: CreateOperationRequest.ProductList:type_name -> InventoryProduct
    4, // 1: GetInventoryProductInfoResponse.ProductList:type_name -> ProductInfo
    0, // 2: productInventoryService.CreateOperation:input_type -> CreateOperationRequest
    3, // 3: productInventoryService.GetInventoryProductInfo:input_type -> GetInventoryProductInfoRequest
    2, // 4: productInventoryService.CreateOperation:output_type -> CreateOperationResponse
    5, // 5: productInventoryService.GetInventoryProductInfo:output_type -> GetInventoryProductInfoResponse
    4, // [4:6] is the sub-list for method output_type
    2, // [2:4] is the sub-list for method input_type
    2, // [2:2] is the sub-list for extension type_name
    2, // [2:2] is the sub-list for extension extendee
    0, // [0:2] is the sub-list for field type_name
}
func init() { file_product_inventory_proto_init() }
func file_product_inventory_proto_init() {
    if File_product_inventory_proto != nil {
        return
    }
    if !protoimpl.UnsafeEnabled {
        file_product_inventory_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
            switch v := v.(*CreateOperationRequest); i {
            case 0:
                return &v.state
            case 1:
                return &v.sizeCache
            case 2:
                return &v.unknownFields
            default:
                return nil
            }
        }
        file_product_inventory_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
            switch v := v.(*InventoryProduct); i {
            case 0:
                return &v.state
            case 1:
                return &v.sizeCache
            case 2:
                return &v.unknownFields
            default:
                return nil
            }
        }
        file_product_inventory_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
            switch v := v.(*CreateOperationResponse); i {
            case 0:
                return &v.state
            case 1:
                return &v.sizeCache
            case 2:
                return &v.unknownFields
            default:
                return nil
            }
        }
        file_product_inventory_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
            switch v := v.(*GetInventoryProductInfoRequest); i {
            case 0:
                return &v.state
            case 1:
                return &v.sizeCache
            case 2:
                return &v.unknownFields
            default:
                return nil
            }
        }
        file_product_inventory_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
            switch v := v.(*ProductInfo); i {
            case 0:
                return &v.state
            case 1:
                return &v.sizeCache
            case 2:
                return &v.unknownFields
            default:
                return nil
            }
        }
        file_product_inventory_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
            switch v := v.(*GetInventoryProductInfoResponse); i {
            case 0:
                return &v.state
            case 1:
                return &v.sizeCache
            case 2:
                return &v.unknownFields
            default:
                return nil
            }
        }
    }
    type x struct{}
    out := protoimpl.TypeBuilder{
        File: protoimpl.DescBuilder{
            GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
            RawDescriptor: file_product_inventory_proto_rawDesc,
            NumEnums:      0,
            NumMessages:   6,
            NumExtensions: 0,
            NumServices:   1,
        },
        GoTypes:           file_product_inventory_proto_goTypes,
        DependencyIndexes: file_product_inventory_proto_depIdxs,
        MessageInfos:      file_product_inventory_proto_msgTypes,
    }.Build()
    File_product_inventory_proto = out.File
    file_product_inventory_proto_rawDesc = nil
    file_product_inventory_proto_goTypes = nil
    file_product_inventory_proto_depIdxs = nil
}
proto/product_inventory/product_inventory_grpc.pb.go
New file
@@ -0,0 +1,138 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package product_inventory
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
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// ProductInventoryServiceClient is the client API for ProductInventoryService 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 ProductInventoryServiceClient interface {
    CreateOperation(ctx context.Context, in *CreateOperationRequest, opts ...grpc.CallOption) (*CreateOperationResponse, error)
    GetInventoryProductInfo(ctx context.Context, in *GetInventoryProductInfoRequest, opts ...grpc.CallOption) (*GetInventoryProductInfoResponse, error)
}
type productInventoryServiceClient struct {
    cc grpc.ClientConnInterface
}
func NewProductInventoryServiceClient(cc grpc.ClientConnInterface) ProductInventoryServiceClient {
    return &productInventoryServiceClient{cc}
}
func (c *productInventoryServiceClient) CreateOperation(ctx context.Context, in *CreateOperationRequest, opts ...grpc.CallOption) (*CreateOperationResponse, error) {
    out := new(CreateOperationResponse)
    err := c.cc.Invoke(ctx, "/productInventoryService/CreateOperation", in, out, opts...)
    if err != nil {
        return nil, err
    }
    return out, nil
}
func (c *productInventoryServiceClient) GetInventoryProductInfo(ctx context.Context, in *GetInventoryProductInfoRequest, opts ...grpc.CallOption) (*GetInventoryProductInfoResponse, error) {
    out := new(GetInventoryProductInfoResponse)
    err := c.cc.Invoke(ctx, "/productInventoryService/GetInventoryProductInfo", in, out, opts...)
    if err != nil {
        return nil, err
    }
    return out, nil
}
// ProductInventoryServiceServer is the server API for ProductInventoryService service.
// All implementations must embed UnimplementedProductInventoryServiceServer
// for forward compatibility
type ProductInventoryServiceServer interface {
    CreateOperation(context.Context, *CreateOperationRequest) (*CreateOperationResponse, error)
    GetInventoryProductInfo(context.Context, *GetInventoryProductInfoRequest) (*GetInventoryProductInfoResponse, error)
    mustEmbedUnimplementedProductInventoryServiceServer()
}
// UnimplementedProductInventoryServiceServer must be embedded to have forward compatible implementations.
type UnimplementedProductInventoryServiceServer struct {
}
func (UnimplementedProductInventoryServiceServer) CreateOperation(context.Context, *CreateOperationRequest) (*CreateOperationResponse, error) {
    return nil, status.Errorf(codes.Unimplemented, "method CreateOperation not implemented")
}
func (UnimplementedProductInventoryServiceServer) GetInventoryProductInfo(context.Context, *GetInventoryProductInfoRequest) (*GetInventoryProductInfoResponse, error) {
    return nil, status.Errorf(codes.Unimplemented, "method GetInventoryProductInfo not implemented")
}
func (UnimplementedProductInventoryServiceServer) mustEmbedUnimplementedProductInventoryServiceServer() {
}
// UnsafeProductInventoryServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ProductInventoryServiceServer will
// result in compilation errors.
type UnsafeProductInventoryServiceServer interface {
    mustEmbedUnimplementedProductInventoryServiceServer()
}
func RegisterProductInventoryServiceServer(s grpc.ServiceRegistrar, srv ProductInventoryServiceServer) {
    s.RegisterService(&ProductInventoryService_ServiceDesc, srv)
}
func _ProductInventoryService_CreateOperation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
    in := new(CreateOperationRequest)
    if err := dec(in); err != nil {
        return nil, err
    }
    if interceptor == nil {
        return srv.(ProductInventoryServiceServer).CreateOperation(ctx, in)
    }
    info := &grpc.UnaryServerInfo{
        Server:     srv,
        FullMethod: "/productInventoryService/CreateOperation",
    }
    handler := func(ctx context.Context, req interface{}) (interface{}, error) {
        return srv.(ProductInventoryServiceServer).CreateOperation(ctx, req.(*CreateOperationRequest))
    }
    return interceptor(ctx, in, info, handler)
}
func _ProductInventoryService_GetInventoryProductInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
    in := new(GetInventoryProductInfoRequest)
    if err := dec(in); err != nil {
        return nil, err
    }
    if interceptor == nil {
        return srv.(ProductInventoryServiceServer).GetInventoryProductInfo(ctx, in)
    }
    info := &grpc.UnaryServerInfo{
        Server:     srv,
        FullMethod: "/productInventoryService/GetInventoryProductInfo",
    }
    handler := func(ctx context.Context, req interface{}) (interface{}, error) {
        return srv.(ProductInventoryServiceServer).GetInventoryProductInfo(ctx, req.(*GetInventoryProductInfoRequest))
    }
    return interceptor(ctx, in, info, handler)
}
// ProductInventoryService_ServiceDesc is the grpc.ServiceDesc for ProductInventoryService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ProductInventoryService_ServiceDesc = grpc.ServiceDesc{
    ServiceName: "productInventoryService",
    HandlerType: (*ProductInventoryServiceServer)(nil),
    Methods: []grpc.MethodDesc{
        {
            MethodName: "CreateOperation",
            Handler:    _ProductInventoryService_CreateOperation_Handler,
        },
        {
            MethodName: "GetInventoryProductInfo",
            Handler:    _ProductInventoryService_GetInventoryProductInfo_Handler,
        },
    },
    Streams:  []grpc.StreamDesc{},
    Metadata: "product_inventory.proto",
}
proto/product_inventory/server.go
New file
@@ -0,0 +1,182 @@
package product_inventory
import (
    "context"
    "errors"
    "github.com/shopspring/decimal"
    "strconv"
    "strings"
    "time"
    "wms/constvar"
    "wms/models"
    "wms/pkg/timex"
)
type Server struct {
    UnimplementedProductInventoryServiceServer
}
type ProductAndLocationInfo struct {
    ProductId  string          `json:"productId"`
    Amount     decimal.Decimal `json:"amount"`
    LocationId int             `json:"locationId"`
}
func (s *Server) GetInventoryProductInfo(ctx context.Context, req *GetInventoryProductInfoRequest) (*GetInventoryProductInfoResponse, error) {
    if req.Number == "" {
        return nil, errors.New("参数不能为空")
    }
    //查询产品id
    var details []ProductAndLocationInfo
    var productIds []string
    err := models.NewOperationDetailsSearch().Orm.Model(&models.OperationDetails{}).
        Select("wms_operation_details.product_id,wms_operation_details.amount,wms_operation.from_location_id as location_id").
        Joins("left join wms_operation on wms_operation.id = wms_operation_details.operation_id").
        Where("wms_operation.source_number = ?", req.Number).Find(&details).Error
    if err != nil {
        return nil, err
    }
    var locationId int
    for _, detail := range details {
        productIds = append(productIds, detail.ProductId)
        locationId = detail.LocationId
    }
    //查询产品信息
    materials, err := models.NewMaterialSearch().SetIDs(productIds).FindNotTotal()
    if err != nil {
        return nil, err
    }
    //查询位置信息
    location, err := models.NewLocationSearch().SetID(locationId).First()
    if err != nil {
        return nil, err
    }
    //根据仓库缩写查询仓库
    code := strings.Split(location.JointName, "/")[0]
    warehouse, err := models.NewWarehouseSearch().SetCode(code).First()
    if err != nil {
        return nil, err
    }
    //统计仓库下所有位置的产品在库数量
    locations, err := models.NewLocationSearch().SetJointName(code).FindNotTotal()
    if err != nil {
        return nil, err
    }
    var locationIds []int
    for _, l := range locations {
        locationIds = append(locationIds, l.Id)
    }
    amounts, err := models.NewLocationProductAmountSearch().SetProductIds(productIds).SetLocationIds(locationIds).Find()
    if err != nil {
        return nil, err
    }
    var inventory []ProductAndLocationInfo
    for _, productAmount := range amounts {
        var in ProductAndLocationInfo
        in.ProductId = productAmount.ProductId
        in.Amount = productAmount.Amount
        inventory = append(inventory, in)
    }
    //统计可用数量
    var canUse []ProductAndLocationInfo
    err = models.NewOperationDetailsSearch().Orm.Model(&models.OperationDetails{}).
        Select("wms_operation_details.product_id, wms_operation_details.amount").
        Joins("left join wms_operation on wms_operation_details.operation_id = wms_operation.id").
        Where("wms_operation_details.product_id in (?)", productIds).
        Where("wms_operation.from_location_id in (?)", locationIds).Where("wms_operation.status = ?", constvar.OperationStatus_Ready).
        Where("wms_operation.base_operation_type in (?)", []constvar.BaseOperationType{constvar.BaseOperationTypeOutgoing, constvar.BaseOperationTypeInternal}).
        Find(&canUse).Error
    if err != nil {
        return nil, err
    }
    products := make([]*ProductInfo, 0)
    for _, material := range materials {
        var p ProductInfo
        p.Id = material.ID
        p.Name = material.Name
        for _, detail := range details {
            if material.ID == detail.ProductId {
                p.OrderAmount = detail.Amount.String()
                break
            }
        }
        p.Unit = material.Unit
        p.SalePrice = material.SalePrice.String()
        p.Warehouse = warehouse.Name
        at := decimal.NewFromInt(0)
        for _, info := range inventory {
            if material.ID == info.ProductId {
                at = at.Add(info.Amount)
            }
        }
        p.Amount = at.String()
        cu := decimal.NewFromInt(0)
        for _, info := range canUse {
            if material.ID == info.ProductId {
                cu = cu.Add(info.Amount)
            }
        }
        p.AvailableNumber = cu.String()
        products = append(products, &p)
    }
    resp := new(GetInventoryProductInfoResponse)
    resp.ProductList = products
    return resp, nil
}
func (s *Server) CreateOperation(ctx context.Context, req *CreateOperationRequest) (*CreateOperationResponse, error) {
    var operations []*models.Operation
    var operation models.Operation
    var details []*models.OperationDetails
    operation.SourceNumber = req.Number
    operation.OperationDate = timex.TimeToString2(time.Now())
    operation.Number = strconv.FormatInt(time.Now().Unix(), 10)
    operation.Status = constvar.OperationStatus_Ready
    warehouse, err := models.NewWarehouseSearch().First()
    if err != nil {
        return nil, err
    }
    operationType, err := models.NewOperationTypeSearch().SetWarehouseId(warehouse.Id).SetBaseOperationType(constvar.BaseOperationTypeOutgoing).First()
    if err != nil {
        return nil, err
    }
    operation.OperationTypeName = operationType.Name
    operation.OperationTypeId = operationType.Id
    location, err := models.NewLocationSearch().SetJointNames([]string{warehouse.Code}).First()
    if err != nil {
        return nil, err
    }
    operation.FromLocationID = location.Id
    first, err := models.NewLocationSearch().SetType(int(constvar.LocationTypeCustomer)).First()
    if err != nil {
        return nil, err
    }
    operation.ToLocationID = first.Id
    operation.BaseOperationType = constvar.BaseOperationTypeOutgoing
    if req.DeliverType == 1 {
        for _, product := range req.ProductList {
            var detail models.OperationDetails
            detail.ProductId = product.Id
            amount, _ := decimal.NewFromString(product.Amount)
            detail.Amount = amount
            details = append(details, &detail)
        }
        operation.Details = details
        operations = append(operations, &operation)
    } else {
        for _, product := range req.ProductList {
            newOperation := operation
            var detail models.OperationDetails
            detail.ProductId = product.Id
            amount, _ := decimal.NewFromString(product.Amount)
            detail.Amount = amount
            details = append(details, &detail)
            newOperation.Details = append(newOperation.Details, &detail)
            operations = append(operations, &newOperation)
        }
    }
    err = models.NewOperationSearch().CreateBatch(operations)
    resp := new(CreateOperationResponse)
    return resp, err
}