From 6f567319be16b117a66ecd0bf5ec0ba066e65a0a Mon Sep 17 00:00:00 2001 From: zzw <1464003642@qq.com> Date: Fri, 28 Aug 2026 10:49:09 +0800 Subject: [PATCH] feat: sale manager --- .gitea/workflows/cd-test.yml | 1 + .gitea/workflows/ci.yml | 35 +- pkg/modelbase/base.go | 12 + rpc/chore/chore.pb | Bin 14061 -> 14336 bytes rpc/chore/chore.proto | 18 + rpc/chore/pb/chore.pb.go | 123 +- rpc/chore/pb/chore_grpc.pb.go | 80 +- rpc/product/pb/product.pb.go | 274 ++-- rpc/product/pb/product_grpc.pb.go | 41 + rpc/product/product.pb | Bin 19471 -> 19670 bytes rpc/product/product.proto | 13 + rpc/sale/pb/sale.pb.go | 1175 +++++++++++++++++ rpc/sale/pb/sale_grpc.pb.go | 505 +++++++ rpc/sale/sale.pb | Bin 0 -> 16510 bytes rpc/sale/sale.proto | 173 +++ services/ad/internal/logic/createLogic.go | 2 +- services/ad/internal/logic/editLogic.go | 2 +- services/ad/internal/logic/itemsLogic.go | 4 +- services/ad/internal/logic/response.go | 7 +- services/ad/internal/logic/statusLogic.go | 2 +- services/ad/internal/logic/webItemsLogic.go | 2 +- services/chore/chore.go | 45 +- services/chore/choreclient/chore.go | 20 +- services/chore/internal/dao/region.go | 10 + .../internal/logic/decryptMobileLogic.go | 52 + services/chore/internal/logic/regionsLogic.go | 54 + services/chore/internal/logic/testLogic.go | 44 +- services/chore/internal/model/region.go | 18 + services/chore/internal/server/choreServer.go | 10 + services/chore/internal/svc/servicecontext.go | 11 +- services/chore/run.toml | 21 +- .../product/internal/logic/createlogic.go | 2 +- .../product/internal/logic/editapplylogic.go | 4 +- .../product/internal/logic/editbaselogic.go | 2 +- .../internal/logic/editsusceptiblelogic.go | 2 +- services/product/internal/logic/infologic.go | 2 +- services/product/internal/logic/itemslogic.go | 4 +- services/product/internal/logic/nameslogic.go | 2 +- .../product/internal/logic/numberAddLogic.go | 5 +- .../internal/logic/numberItemsLogic.go | 78 ++ .../product/internal/logic/numberLogic.go | 5 +- services/product/internal/logic/response.go | 7 +- services/product/internal/logic/sortlogic.go | 2 +- .../product/internal/logic/statuslogic.go | 2 +- .../product/internal/logic/verifylogic.go | 8 +- .../internal/logic/verifystatuslogic.go | 2 +- .../product/internal/model/product_model.go | 9 +- .../product/internal/server/productserver.go | 6 + services/product/productClient/product.go | 10 + services/product/validator/validator.go | 11 + services/sale/.gitignore | 2 + services/sale/Dockerfile | 39 + services/sale/etc/sale.yaml | 7 + services/sale/internal/config/config.go | 13 + services/sale/internal/dao/sale.go | 131 ++ services/sale/internal/dao/sale_group.go | 22 + services/sale/internal/logic/createLogic.go | 91 ++ services/sale/internal/logic/editLogic.go | 97 ++ .../sale/internal/logic/groupCreateLogic.go | 65 + .../sale/internal/logic/groupItemsLogic.go | 68 + .../sale/internal/logic/groupNamesLogic.go | 41 + services/sale/internal/logic/helper.go | 94 ++ services/sale/internal/logic/infoLogic.go | 51 + services/sale/internal/logic/itemsLogic.go | 89 ++ .../sale/internal/logic/namesInternalLogic.go | 57 + services/sale/internal/logic/namesLogic.go | 41 + services/sale/internal/logic/response.go | 39 + services/sale/internal/logic/statusLogic.go | 74 ++ services/sale/internal/logic/typesLogic.go | 28 + .../sale/internal/model/sale_group_model.go | 23 + services/sale/internal/model/sale_model.go | 23 + services/sale/internal/server/saleServer.go | 81 ++ services/sale/internal/svc/serviceContext.go | 22 + services/sale/run.toml | 55 + services/sale/sale.go | 150 +++ services/sale/saleClient/sale.go | 112 ++ services/sale/validator/validator.go | 200 +++ services/user/internal/dao/user.go | 1 + .../internal/logic/registerByUserLogic.go | 2 +- services/user/internal/logic/registerLogic.go | 2 +- services/user/internal/logic/response.go | 2 +- .../user/internal/logic/userItemsLogic.go | 34 +- 82 files changed, 4491 insertions(+), 182 deletions(-) create mode 100644 rpc/sale/pb/sale.pb.go create mode 100644 rpc/sale/pb/sale_grpc.pb.go create mode 100644 rpc/sale/sale.pb create mode 100644 rpc/sale/sale.proto create mode 100644 services/chore/internal/dao/region.go create mode 100644 services/chore/internal/logic/decryptMobileLogic.go create mode 100644 services/chore/internal/logic/regionsLogic.go create mode 100644 services/chore/internal/model/region.go create mode 100644 services/product/internal/logic/numberItemsLogic.go create mode 100644 services/sale/.gitignore create mode 100644 services/sale/Dockerfile create mode 100644 services/sale/etc/sale.yaml create mode 100644 services/sale/internal/config/config.go create mode 100644 services/sale/internal/dao/sale.go create mode 100644 services/sale/internal/dao/sale_group.go create mode 100644 services/sale/internal/logic/createLogic.go create mode 100644 services/sale/internal/logic/editLogic.go create mode 100644 services/sale/internal/logic/groupCreateLogic.go create mode 100644 services/sale/internal/logic/groupItemsLogic.go create mode 100644 services/sale/internal/logic/groupNamesLogic.go create mode 100644 services/sale/internal/logic/helper.go create mode 100644 services/sale/internal/logic/infoLogic.go create mode 100644 services/sale/internal/logic/itemsLogic.go create mode 100644 services/sale/internal/logic/namesInternalLogic.go create mode 100644 services/sale/internal/logic/namesLogic.go create mode 100644 services/sale/internal/logic/response.go create mode 100644 services/sale/internal/logic/statusLogic.go create mode 100644 services/sale/internal/logic/typesLogic.go create mode 100644 services/sale/internal/model/sale_group_model.go create mode 100644 services/sale/internal/model/sale_model.go create mode 100644 services/sale/internal/server/saleServer.go create mode 100644 services/sale/internal/svc/serviceContext.go create mode 100644 services/sale/run.toml create mode 100644 services/sale/sale.go create mode 100644 services/sale/saleClient/sale.go create mode 100644 services/sale/validator/validator.go diff --git a/.gitea/workflows/cd-test.yml b/.gitea/workflows/cd-test.yml index 9e2614c..5049232 100644 --- a/.gitea/workflows/cd-test.yml +++ b/.gitea/workflows/cd-test.yml @@ -39,4 +39,5 @@ jobs: docker pull ${{ vars.REGISTRY }}/lone/product:latest docker pull ${{ vars.REGISTRY }}/lone/admin:latest docker pull ${{ vars.REGISTRY }}/lone/user:latest + docker pull ${{ vars.REGISTRY }}/lone/chore:latest docker compose up -d diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 9b0ffaf..d13881d 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -11,11 +11,13 @@ on: - "services/user/**" - "services/ad/**" - "services/chore/**" + - "services/sale/**" - "rpc/product/**" - "rpc/admin/**" - "rpc/user/**" - "rpc/ad/**" - "rpc/chore/**" + - "rpc/sale/**" - "pkg/**" - ".gitea/workflows/ci.yml" workflow_dispatch: @@ -30,6 +32,7 @@ jobs: user: ${{ steps.filter.outputs.user }} ad: ${{ steps.filter.outputs.ad }} chore: ${{ steps.filter.outputs.chore }} + sale: ${{ steps.filter.outputs.sale }} steps: - name: Checkout uses: https://git.ailuowan.com/deploy/checkout@v4 @@ -45,6 +48,7 @@ jobs: user=false ad=false chore=false + sale=false if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then bff=true @@ -53,6 +57,7 @@ jobs: user=true ad=true chore=true + sale=true else before="${{ github.event.before }}" if [ -z "$before" ] || [ "$before" = "0000000000000000000000000000000000000000" ]; then @@ -70,6 +75,7 @@ jobs: echo "$changed" | grep -qE '^(services/user|rpc/user|pkg)/|^\.gitea/workflows/ci\.yml$' && user=true || true echo "$changed" | grep -qE '^(services/ad|rpc/ad|pkg)/|^\.gitea/workflows/ci\.yml$' && ad=true || true echo "$changed" | grep -qE '^(services/chore|rpc/chore|pkg)/|^\.gitea/workflows/ci\.yml$' && chore=true || true + echo "$changed" | grep -qE '^(services/sale|rpc/sale|pkg)/|^\.gitea/workflows/ci\.yml$' && sale=true || true fi echo "bff=$bff" >> "$GITHUB_OUTPUT" @@ -78,7 +84,8 @@ jobs: echo "user=$user" >> "$GITHUB_OUTPUT" echo "ad=$ad" >> "$GITHUB_OUTPUT" echo "chore=$chore" >> "$GITHUB_OUTPUT" - echo "bff=$bff product=$product admin=$admin user=$user ad=$ad chore=$chore" + echo "sale=$sale" >> "$GITHUB_OUTPUT" + echo "bff=$bff product=$product admin=$admin user=$user ad=$ad chore=$chore sale=$sale" docker-bff: needs: changes @@ -232,6 +239,32 @@ jobs: -t ${{ vars.REGISTRY }}/$NAME:latest \ . + - name: Docker push + run: | + docker push ${{ vars.REGISTRY }}/$NAME:latest + + docker-sale: + needs: changes + if: needs.changes.outputs.sale == 'true' + runs-on: runner + env: + NAME: lone/sale + steps: + - name: Checkout + uses: https://git.ailuowan.com/deploy/checkout@v4 + + - name: Login Registry + run: | + echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ vars.REGISTRY }} -u "${{ vars.REGISTRY_USERNAME }}" --password-stdin + + - name: Docker build + run: | + docker buildx use default + docker buildx build --builder default --load \ + -f services/sale/Dockerfile \ + -t ${{ vars.REGISTRY }}/$NAME:latest \ + . + - name: Docker push run: | docker push ${{ vars.REGISTRY }}/$NAME:latest \ No newline at end of file diff --git a/pkg/modelbase/base.go b/pkg/modelbase/base.go index 6b4935f..5ded0e8 100644 --- a/pkg/modelbase/base.go +++ b/pkg/modelbase/base.go @@ -128,6 +128,11 @@ func (m Base) session() *gorm.DB { return o } +// Session returns the DB session for this model (honors WithTX). +func (m Base) Session() *gorm.DB { + return m.session() +} + // Create inserts a row. func (m Base) Create(data interface{}) error { return m.session().Create(data).Error @@ -139,6 +144,13 @@ func (m Base) Edit(w Params, data interface{}) (int64, error) { update := make(map[string]interface{}) jsonBytes, _ := jsoniter.Marshal(data) _ = jsoniter.Unmarshal(jsonBytes, &update) + for k, v := range update { + if nested, ok := v.(map[string]interface{}); ok { + if b, err := jsoniter.Marshal(nested); err == nil { + update[k] = string(b) + } + } + } ret := o.Updates(update) return ret.RowsAffected, ignoreNotFound(ret.Error) } diff --git a/rpc/chore/chore.pb b/rpc/chore/chore.pb index 896cfa54f6869d38738d9eae41e78fe36d11b0d7..cd54c0ab0ca9a4bac1e89956cc655c4ca3dd538f 100644 GIT binary patch delta 303 zcmaEx+fcB<$&_gi>tq+xN9juDTmmks$wid~CBFGdnK`LJsf9wyT)g>3ndzB%@ws3z z2}T7*4bC7Qh#*9rk|q~dP-=Q+eqJ$1i!>K!L1IyAUP*jr3RpR75C=rSGsWlv(_~Gv zh4n)5T)ZfD35n|^XXF>9>Y<1Njg#VsN(7}A7XWQYRZ?lX{A4ndoRExuVnL>UnXx`t sqkam+>G}|N3i)ucL)|1K2sZ)dMgvS!Wx=M33yGqdS_JXeSy$&_g&^JEv(N6bbG87KFeEu4JUTp0k9ZwjUW diff --git a/rpc/chore/chore.proto b/rpc/chore/chore.proto index 66de98d..c4b3e41 100644 --- a/rpc/chore/chore.proto +++ b/rpc/chore/chore.proto @@ -17,6 +17,16 @@ service Chore { body: "*" }; } + rpc DecryptMobile(DecryptMobileReq) returns (Response) { + option (google.api.http) = { + get: "/api/v3/chore/decrypt/mobile" + }; + } + rpc Regions(RegionsReq) returns (Response) { + option (google.api.http) = { + get: "/api/v3/chore/regions" + }; + } } message Response { @@ -33,4 +43,12 @@ message TestReq { int32 id = 1; repeated int64 ids = 2; uint32 number = 3; +} + +message DecryptMobileReq { + string origin_mobile = 1; +} + +message RegionsReq { + int32 parent_id = 1; } \ No newline at end of file diff --git a/rpc/chore/pb/chore.pb.go b/rpc/chore/pb/chore.pb.go index b688f13..2b17b87 100644 --- a/rpc/chore/pb/chore.pb.go +++ b/rpc/chore/pb/chore.pb.go @@ -186,6 +186,94 @@ func (x *TestReq) GetNumber() uint32 { return 0 } +type DecryptMobileReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + OriginMobile string `protobuf:"bytes,1,opt,name=origin_mobile,json=originMobile,proto3" json:"origin_mobile,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DecryptMobileReq) Reset() { + *x = DecryptMobileReq{} + mi := &file_chore_chore_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DecryptMobileReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DecryptMobileReq) ProtoMessage() {} + +func (x *DecryptMobileReq) ProtoReflect() protoreflect.Message { + mi := &file_chore_chore_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DecryptMobileReq.ProtoReflect.Descriptor instead. +func (*DecryptMobileReq) Descriptor() ([]byte, []int) { + return file_chore_chore_proto_rawDescGZIP(), []int{3} +} + +func (x *DecryptMobileReq) GetOriginMobile() string { + if x != nil { + return x.OriginMobile + } + return "" +} + +type RegionsReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + ParentId int32 `protobuf:"varint,1,opt,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegionsReq) Reset() { + *x = RegionsReq{} + mi := &file_chore_chore_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegionsReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegionsReq) ProtoMessage() {} + +func (x *RegionsReq) ProtoReflect() protoreflect.Message { + mi := &file_chore_chore_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegionsReq.ProtoReflect.Descriptor instead. +func (*RegionsReq) Descriptor() ([]byte, []int) { + return file_chore_chore_proto_rawDescGZIP(), []int{4} +} + +func (x *RegionsReq) GetParentId() int32 { + if x != nil { + return x.ParentId + } + return 0 +} + var File_chore_chore_proto protoreflect.FileDescriptor const file_chore_chore_proto_rawDesc = "" + @@ -200,10 +288,17 @@ const file_chore_chore_proto_rawDesc = "" + "\aTestReq\x12\x0e\n" + "\x02id\x18\x01 \x01(\x05R\x02id\x12\x10\n" + "\x03ids\x18\x02 \x03(\x03R\x03ids\x12\x16\n" + - "\x06number\x18\x03 \x01(\rR\x06number2\xa1\x01\n" + + "\x06number\x18\x03 \x01(\rR\x06number\"7\n" + + "\x10DecryptMobileReq\x12#\n" + + "\rorigin_mobile\x18\x01 \x01(\tR\foriginMobile\")\n" + + "\n" + + "RegionsReq\x12\x1b\n" + + "\tparent_id\x18\x01 \x01(\x05R\bparentId2\xd0\x02\n" + "\x05Chore\x12P\n" + "\x06Policy\x12\x10.chore.PolicyReq\x1a\x0f.chore.Response\"#\x82\xd3\xe4\x93\x02\x1d:\x01*\x12\x18/api/v3/chore/oss/policy\x12F\n" + - "\x04Test\x12\x0e.chore.TestReq\x1a\x0f.chore.Response\"\x1d\x82\xd3\xe4\x93\x02\x17:\x01*\"\x12/api/v3/chore/testB\x19Z\x17lone-services/rpc/choreb\x06proto3" + "\x04Test\x12\x0e.chore.TestReq\x1a\x0f.chore.Response\"\x1d\x82\xd3\xe4\x93\x02\x17:\x01*\"\x12/api/v3/chore/test\x12_\n" + + "\rDecryptMobile\x12\x17.chore.DecryptMobileReq\x1a\x0f.chore.Response\"$\x82\xd3\xe4\x93\x02\x1e\x12\x1c/api/v3/chore/decrypt/mobile\x12L\n" + + "\aRegions\x12\x11.chore.RegionsReq\x1a\x0f.chore.Response\"\x1d\x82\xd3\xe4\x93\x02\x17\x12\x15/api/v3/chore/regionsB\x19Z\x17lone-services/rpc/choreb\x06proto3" var ( file_chore_chore_proto_rawDescOnce sync.Once @@ -217,19 +312,25 @@ func file_chore_chore_proto_rawDescGZIP() []byte { return file_chore_chore_proto_rawDescData } -var file_chore_chore_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_chore_chore_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_chore_chore_proto_goTypes = []any{ - (*Response)(nil), // 0: chore.Response - (*PolicyReq)(nil), // 1: chore.PolicyReq - (*TestReq)(nil), // 2: chore.TestReq + (*Response)(nil), // 0: chore.Response + (*PolicyReq)(nil), // 1: chore.PolicyReq + (*TestReq)(nil), // 2: chore.TestReq + (*DecryptMobileReq)(nil), // 3: chore.DecryptMobileReq + (*RegionsReq)(nil), // 4: chore.RegionsReq } var file_chore_chore_proto_depIdxs = []int32{ 1, // 0: chore.Chore.Policy:input_type -> chore.PolicyReq 2, // 1: chore.Chore.Test:input_type -> chore.TestReq - 0, // 2: chore.Chore.Policy:output_type -> chore.Response - 0, // 3: chore.Chore.Test:output_type -> chore.Response - 2, // [2:4] is the sub-list for method output_type - 0, // [0:2] is the sub-list for method input_type + 3, // 2: chore.Chore.DecryptMobile:input_type -> chore.DecryptMobileReq + 4, // 3: chore.Chore.Regions:input_type -> chore.RegionsReq + 0, // 4: chore.Chore.Policy:output_type -> chore.Response + 0, // 5: chore.Chore.Test:output_type -> chore.Response + 0, // 6: chore.Chore.DecryptMobile:output_type -> chore.Response + 0, // 7: chore.Chore.Regions:output_type -> chore.Response + 4, // [4:8] is the sub-list for method output_type + 0, // [0:4] 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 @@ -246,7 +347,7 @@ func file_chore_chore_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_chore_chore_proto_rawDesc), len(file_chore_chore_proto_rawDesc)), NumEnums: 0, - NumMessages: 3, + NumMessages: 5, NumExtensions: 0, NumServices: 1, }, diff --git a/rpc/chore/pb/chore_grpc.pb.go b/rpc/chore/pb/chore_grpc.pb.go index 6b84e16..0cae512 100644 --- a/rpc/chore/pb/chore_grpc.pb.go +++ b/rpc/chore/pb/chore_grpc.pb.go @@ -19,8 +19,10 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - Chore_Policy_FullMethodName = "/chore.Chore/Policy" - Chore_Test_FullMethodName = "/chore.Chore/Test" + Chore_Policy_FullMethodName = "/chore.Chore/Policy" + Chore_Test_FullMethodName = "/chore.Chore/Test" + Chore_DecryptMobile_FullMethodName = "/chore.Chore/DecryptMobile" + Chore_Regions_FullMethodName = "/chore.Chore/Regions" ) // ChoreClient is the client API for Chore service. @@ -29,6 +31,8 @@ const ( type ChoreClient interface { Policy(ctx context.Context, in *PolicyReq, opts ...grpc.CallOption) (*Response, error) Test(ctx context.Context, in *TestReq, opts ...grpc.CallOption) (*Response, error) + DecryptMobile(ctx context.Context, in *DecryptMobileReq, opts ...grpc.CallOption) (*Response, error) + Regions(ctx context.Context, in *RegionsReq, opts ...grpc.CallOption) (*Response, error) } type choreClient struct { @@ -59,12 +63,34 @@ func (c *choreClient) Test(ctx context.Context, in *TestReq, opts ...grpc.CallOp return out, nil } +func (c *choreClient) DecryptMobile(ctx context.Context, in *DecryptMobileReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Chore_DecryptMobile_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *choreClient) Regions(ctx context.Context, in *RegionsReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Chore_Regions_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // ChoreServer is the server API for Chore service. // All implementations must embed UnimplementedChoreServer // for forward compatibility. type ChoreServer interface { Policy(context.Context, *PolicyReq) (*Response, error) Test(context.Context, *TestReq) (*Response, error) + DecryptMobile(context.Context, *DecryptMobileReq) (*Response, error) + Regions(context.Context, *RegionsReq) (*Response, error) mustEmbedUnimplementedChoreServer() } @@ -81,6 +107,12 @@ func (UnimplementedChoreServer) Policy(context.Context, *PolicyReq) (*Response, func (UnimplementedChoreServer) Test(context.Context, *TestReq) (*Response, error) { return nil, status.Error(codes.Unimplemented, "method Test not implemented") } +func (UnimplementedChoreServer) DecryptMobile(context.Context, *DecryptMobileReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method DecryptMobile not implemented") +} +func (UnimplementedChoreServer) Regions(context.Context, *RegionsReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method Regions not implemented") +} func (UnimplementedChoreServer) mustEmbedUnimplementedChoreServer() {} func (UnimplementedChoreServer) testEmbeddedByValue() {} @@ -138,6 +170,42 @@ func _Chore_Test_Handler(srv interface{}, ctx context.Context, dec func(interfac return interceptor(ctx, in, info, handler) } +func _Chore_DecryptMobile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DecryptMobileReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ChoreServer).DecryptMobile(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Chore_DecryptMobile_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ChoreServer).DecryptMobile(ctx, req.(*DecryptMobileReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Chore_Regions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RegionsReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ChoreServer).Regions(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Chore_Regions_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ChoreServer).Regions(ctx, req.(*RegionsReq)) + } + return interceptor(ctx, in, info, handler) +} + // Chore_ServiceDesc is the grpc.ServiceDesc for Chore service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -153,6 +221,14 @@ var Chore_ServiceDesc = grpc.ServiceDesc{ MethodName: "Test", Handler: _Chore_Test_Handler, }, + { + MethodName: "DecryptMobile", + Handler: _Chore_DecryptMobile_Handler, + }, + { + MethodName: "Regions", + Handler: _Chore_Regions_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "chore/chore.proto", diff --git a/rpc/product/pb/product.pb.go b/rpc/product/pb/product.pb.go index 075acd7..58e288f 100644 --- a/rpc/product/pb/product.pb.go +++ b/rpc/product/pb/product.pb.go @@ -1263,6 +1263,111 @@ func (x *NumberReq) GetNumber() uint32 { return 0 } +type NumberItem struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Number uint32 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *NumberItem) Reset() { + *x = NumberItem{} + mi := &file_product_product_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NumberItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NumberItem) ProtoMessage() {} + +func (x *NumberItem) ProtoReflect() protoreflect.Message { + mi := &file_product_product_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NumberItem.ProtoReflect.Descriptor instead. +func (*NumberItem) Descriptor() ([]byte, []int) { + return file_product_product_proto_rawDescGZIP(), []int{17} +} + +func (x *NumberItem) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *NumberItem) GetNumber() uint32 { + if x != nil { + return x.Number + } + return 0 +} + +// type: 1 增加, 2 减少 +type NumberItemsReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + Type uint32 `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"` + Items []*NumberItem `protobuf:"bytes,2,rep,name=items,proto3" json:"items,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *NumberItemsReq) Reset() { + *x = NumberItemsReq{} + mi := &file_product_product_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NumberItemsReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NumberItemsReq) ProtoMessage() {} + +func (x *NumberItemsReq) ProtoReflect() protoreflect.Message { + mi := &file_product_product_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NumberItemsReq.ProtoReflect.Descriptor instead. +func (*NumberItemsReq) Descriptor() ([]byte, []int) { + return file_product_product_proto_rawDescGZIP(), []int{18} +} + +func (x *NumberItemsReq) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +func (x *NumberItemsReq) GetItems() []*NumberItem { + if x != nil { + return x.Items + } + return nil +} + type NumberAddReq struct { state protoimpl.MessageState `protogen:"open.v1"` Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` @@ -1273,7 +1378,7 @@ type NumberAddReq struct { func (x *NumberAddReq) Reset() { *x = NumberAddReq{} - mi := &file_product_product_proto_msgTypes[17] + mi := &file_product_product_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1285,7 +1390,7 @@ func (x *NumberAddReq) String() string { func (*NumberAddReq) ProtoMessage() {} func (x *NumberAddReq) ProtoReflect() protoreflect.Message { - mi := &file_product_product_proto_msgTypes[17] + mi := &file_product_product_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1298,7 +1403,7 @@ func (x *NumberAddReq) ProtoReflect() protoreflect.Message { // Deprecated: Use NumberAddReq.ProtoReflect.Descriptor instead. func (*NumberAddReq) Descriptor() ([]byte, []int) { - return file_product_product_proto_rawDescGZIP(), []int{17} + return file_product_product_proto_rawDescGZIP(), []int{19} } func (x *NumberAddReq) GetId() int64 { @@ -1325,7 +1430,7 @@ type ItemsData struct { func (x *ItemsData) Reset() { *x = ItemsData{} - mi := &file_product_product_proto_msgTypes[18] + mi := &file_product_product_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1337,7 +1442,7 @@ func (x *ItemsData) String() string { func (*ItemsData) ProtoMessage() {} func (x *ItemsData) ProtoReflect() protoreflect.Message { - mi := &file_product_product_proto_msgTypes[18] + mi := &file_product_product_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1350,7 +1455,7 @@ func (x *ItemsData) ProtoReflect() protoreflect.Message { // Deprecated: Use ItemsData.ProtoReflect.Descriptor instead. func (*ItemsData) Descriptor() ([]byte, []int) { - return file_product_product_proto_rawDescGZIP(), []int{18} + return file_product_product_proto_rawDescGZIP(), []int{20} } func (x *ItemsData) GetCount() int64 { @@ -1377,7 +1482,7 @@ type VerifyItemsData struct { func (x *VerifyItemsData) Reset() { *x = VerifyItemsData{} - mi := &file_product_product_proto_msgTypes[19] + mi := &file_product_product_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1389,7 +1494,7 @@ func (x *VerifyItemsData) String() string { func (*VerifyItemsData) ProtoMessage() {} func (x *VerifyItemsData) ProtoReflect() protoreflect.Message { - mi := &file_product_product_proto_msgTypes[19] + mi := &file_product_product_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1402,7 +1507,7 @@ func (x *VerifyItemsData) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyItemsData.ProtoReflect.Descriptor instead. func (*VerifyItemsData) Descriptor() ([]byte, []int) { - return file_product_product_proto_rawDescGZIP(), []int{19} + return file_product_product_proto_rawDescGZIP(), []int{21} } func (x *VerifyItemsData) GetCount() int64 { @@ -1439,7 +1544,7 @@ type VerifyParams struct { func (x *VerifyParams) Reset() { *x = VerifyParams{} - mi := &file_product_product_proto_msgTypes[20] + mi := &file_product_product_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1451,7 +1556,7 @@ func (x *VerifyParams) String() string { func (*VerifyParams) ProtoMessage() {} func (x *VerifyParams) ProtoReflect() protoreflect.Message { - mi := &file_product_product_proto_msgTypes[20] + mi := &file_product_product_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1464,7 +1569,7 @@ func (x *VerifyParams) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyParams.ProtoReflect.Descriptor instead. func (*VerifyParams) Descriptor() ([]byte, []int) { - return file_product_product_proto_rawDescGZIP(), []int{20} + return file_product_product_proto_rawDescGZIP(), []int{22} } func (x *VerifyParams) GetId() int64 { @@ -1563,7 +1668,7 @@ type VerifyItem struct { func (x *VerifyItem) Reset() { *x = VerifyItem{} - mi := &file_product_product_proto_msgTypes[21] + mi := &file_product_product_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1575,7 +1680,7 @@ func (x *VerifyItem) String() string { func (*VerifyItem) ProtoMessage() {} func (x *VerifyItem) ProtoReflect() protoreflect.Message { - mi := &file_product_product_proto_msgTypes[21] + mi := &file_product_product_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1588,7 +1693,7 @@ func (x *VerifyItem) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyItem.ProtoReflect.Descriptor instead. func (*VerifyItem) Descriptor() ([]byte, []int) { - return file_product_product_proto_rawDescGZIP(), []int{21} + return file_product_product_proto_rawDescGZIP(), []int{23} } func (x *VerifyItem) GetName() string { @@ -1629,7 +1734,7 @@ type NameItem struct { func (x *NameItem) Reset() { *x = NameItem{} - mi := &file_product_product_proto_msgTypes[22] + mi := &file_product_product_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1641,7 +1746,7 @@ func (x *NameItem) String() string { func (*NameItem) ProtoMessage() {} func (x *NameItem) ProtoReflect() protoreflect.Message { - mi := &file_product_product_proto_msgTypes[22] + mi := &file_product_product_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1654,7 +1759,7 @@ func (x *NameItem) ProtoReflect() protoreflect.Message { // Deprecated: Use NameItem.ProtoReflect.Descriptor instead. func (*NameItem) Descriptor() ([]byte, []int) { - return file_product_product_proto_rawDescGZIP(), []int{22} + return file_product_product_proto_rawDescGZIP(), []int{24} } func (x *NameItem) GetId() int64 { @@ -1715,7 +1820,7 @@ type Item struct { func (x *Item) Reset() { *x = Item{} - mi := &file_product_product_proto_msgTypes[23] + mi := &file_product_product_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1727,7 +1832,7 @@ func (x *Item) String() string { func (*Item) ProtoMessage() {} func (x *Item) ProtoReflect() protoreflect.Message { - mi := &file_product_product_proto_msgTypes[23] + mi := &file_product_product_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1740,7 +1845,7 @@ func (x *Item) ProtoReflect() protoreflect.Message { // Deprecated: Use Item.ProtoReflect.Descriptor instead. func (*Item) Descriptor() ([]byte, []int) { - return file_product_product_proto_rawDescGZIP(), []int{23} + return file_product_product_proto_rawDescGZIP(), []int{25} } func (x *Item) GetId() int64 { @@ -2116,7 +2221,14 @@ const file_product_product_proto_rawDesc = "" + "\tNumberReq\x12\x0e\n" + "\x02id\x18\x01 \x01(\x03R\x02id\x12\x12\n" + "\x04type\x18\x02 \x01(\rR\x04type\x12\x16\n" + - "\x06number\x18\x03 \x01(\rR\x06number\"6\n" + + "\x06number\x18\x03 \x01(\rR\x06number\"4\n" + + "\n" + + "NumberItem\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x03R\x02id\x12\x16\n" + + "\x06number\x18\x02 \x01(\rR\x06number\"O\n" + + "\x0eNumberItemsReq\x12\x12\n" + + "\x04type\x18\x01 \x01(\rR\x04type\x12)\n" + + "\x05items\x18\x02 \x03(\v2\x13.product.NumberItemR\x05items\"6\n" + "\fNumberAddReq\x12\x0e\n" + "\x02id\x18\x01 \x01(\x03R\x02id\x12\x16\n" + "\x06number\x18\x02 \x01(\rR\x06number\"F\n" + @@ -2205,7 +2317,7 @@ const file_product_product_proto_rawDesc = "" + "\x06reason\x18\" \x01(\tR\x06reason\x12\x1d\n" + "\n" + "admin_name\x18# \x01(\tR\tadminName\x12\x12\n" + - "\x04edit\x18$ \x01(\rR\x04edit2\xa8\v\n" + + "\x04edit\x18$ \x01(\rR\x04edit2\xe8\v\n" + "\aProduct\x12M\n" + "\x06Create\x12\x12.product.CreateReq\x1a\x11.product.Response\"\x1c\x82\xd3\xe4\x93\x02\x16:\x01*\"\x11/admin/v3/product\x12N\n" + "\x04Info\x12\x10.product.InfoReq\x1a\x11.product.Response\"!\x82\xd3\xe4\x93\x02\x1b:\x01*\x12\x16/admin/v3/product/info\x12K\n" + @@ -2220,7 +2332,8 @@ const file_product_product_proto_rawDesc = "" + "\bEditBase\x12\x14.product.EditBaseReq\x1a\x11.product.Response\"!\x82\xd3\xe4\x93\x02\x1b:\x01*\x1a\x16/admin/v3/product/base\x12k\n" + "\x0fEditSusceptible\x12\x1b.product.EditSusceptibleReq\x1a\x11.product.Response\"(\x82\xd3\xe4\x93\x02\":\x01*\x1a\x1d/admin/v3/product/susceptible\x12k\n" + "\rEditApplyPass\x12\x19.product.EditApplyPassReq\x1a\x11.product.Response\",\x82\xd3\xe4\x93\x02&:\x01*\x1a!/admin/v3/product/edit/apply/pass\x124\n" + - "\x06Number\x12\x12.product.NumberReq\x1a\x16.google.protobuf.Empty\x12/\n" + + "\x06Number\x12\x12.product.NumberReq\x1a\x16.google.protobuf.Empty\x12>\n" + + "\vNumberItems\x12\x17.product.NumberItemsReq\x1a\x16.google.protobuf.Empty\x12/\n" + "\bInfoById\x12\x14.product.InfoByIdReq\x1a\r.product.Item\x12=\n" + "\n" + "ItemsByIds\x12\x16.product.ItemsByIdsReq\x1a\x17.product.ItemsByIdsData\x12Z\n" + @@ -2238,7 +2351,7 @@ func file_product_product_proto_rawDescGZIP() []byte { return file_product_product_proto_rawDescData } -var file_product_product_proto_msgTypes = make([]protoimpl.MessageInfo, 24) +var file_product_product_proto_msgTypes = make([]protoimpl.MessageInfo, 26) var file_product_product_proto_goTypes = []any{ (*Response)(nil), // 0: product.Response (*InfoByIdReq)(nil), // 1: product.InfoByIdReq @@ -2257,60 +2370,65 @@ var file_product_product_proto_goTypes = []any{ (*EditBaseReq)(nil), // 14: product.EditBaseReq (*EditSusceptibleReq)(nil), // 15: product.EditSusceptibleReq (*NumberReq)(nil), // 16: product.NumberReq - (*NumberAddReq)(nil), // 17: product.NumberAddReq - (*ItemsData)(nil), // 18: product.ItemsData - (*VerifyItemsData)(nil), // 19: product.VerifyItemsData - (*VerifyParams)(nil), // 20: product.VerifyParams - (*VerifyItem)(nil), // 21: product.VerifyItem - (*NameItem)(nil), // 22: product.NameItem - (*Item)(nil), // 23: product.Item - (*emptypb.Empty)(nil), // 24: google.protobuf.Empty + (*NumberItem)(nil), // 17: product.NumberItem + (*NumberItemsReq)(nil), // 18: product.NumberItemsReq + (*NumberAddReq)(nil), // 19: product.NumberAddReq + (*ItemsData)(nil), // 20: product.ItemsData + (*VerifyItemsData)(nil), // 21: product.VerifyItemsData + (*VerifyParams)(nil), // 22: product.VerifyParams + (*VerifyItem)(nil), // 23: product.VerifyItem + (*NameItem)(nil), // 24: product.NameItem + (*Item)(nil), // 25: product.Item + (*emptypb.Empty)(nil), // 26: google.protobuf.Empty } var file_product_product_proto_depIdxs = []int32{ - 23, // 0: product.ItemsByIdsData.items:type_name -> product.Item - 23, // 1: product.ItemsData.items:type_name -> product.Item - 21, // 2: product.VerifyItemsData.items:type_name -> product.VerifyItem - 20, // 3: product.VerifyItem.new:type_name -> product.VerifyParams - 20, // 4: product.VerifyItem.old:type_name -> product.VerifyParams - 4, // 5: product.Product.Create:input_type -> product.CreateReq - 5, // 6: product.Product.Info:input_type -> product.InfoReq - 6, // 7: product.Product.Items:input_type -> product.ItemsReq - 7, // 8: product.Product.Names:input_type -> product.NamesReq - 8, // 9: product.Product.Status:input_type -> product.StatusReq - 9, // 10: product.Product.Sort:input_type -> product.SortReq - 10, // 11: product.Product.Verify:input_type -> product.VerifyReq - 11, // 12: product.Product.VerifyFirst:input_type -> product.VerifyStatusReq - 11, // 13: product.Product.VerifySecond:input_type -> product.VerifyStatusReq - 12, // 14: product.Product.EditApply:input_type -> product.EditApplyReq - 14, // 15: product.Product.EditBase:input_type -> product.EditBaseReq - 15, // 16: product.Product.EditSusceptible:input_type -> product.EditSusceptibleReq - 13, // 17: product.Product.EditApplyPass:input_type -> product.EditApplyPassReq - 16, // 18: product.Product.Number:input_type -> product.NumberReq - 1, // 19: product.Product.InfoById:input_type -> product.InfoByIdReq - 2, // 20: product.Product.ItemsByIds:input_type -> product.ItemsByIdsReq - 17, // 21: product.Product.NumberAdd:input_type -> product.NumberAddReq - 0, // 22: product.Product.Create:output_type -> product.Response - 0, // 23: product.Product.Info:output_type -> product.Response - 0, // 24: product.Product.Items:output_type -> product.Response - 0, // 25: product.Product.Names:output_type -> product.Response - 0, // 26: product.Product.Status:output_type -> product.Response - 0, // 27: product.Product.Sort:output_type -> product.Response - 0, // 28: product.Product.Verify:output_type -> product.Response - 0, // 29: product.Product.VerifyFirst:output_type -> product.Response - 0, // 30: product.Product.VerifySecond:output_type -> product.Response - 0, // 31: product.Product.EditApply:output_type -> product.Response - 0, // 32: product.Product.EditBase:output_type -> product.Response - 0, // 33: product.Product.EditSusceptible:output_type -> product.Response - 0, // 34: product.Product.EditApplyPass:output_type -> product.Response - 24, // 35: product.Product.Number:output_type -> google.protobuf.Empty - 23, // 36: product.Product.InfoById:output_type -> product.Item - 3, // 37: product.Product.ItemsByIds:output_type -> product.ItemsByIdsData - 0, // 38: product.Product.NumberAdd:output_type -> product.Response - 22, // [22:39] is the sub-list for method output_type - 5, // [5:22] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 25, // 0: product.ItemsByIdsData.items:type_name -> product.Item + 17, // 1: product.NumberItemsReq.items:type_name -> product.NumberItem + 25, // 2: product.ItemsData.items:type_name -> product.Item + 23, // 3: product.VerifyItemsData.items:type_name -> product.VerifyItem + 22, // 4: product.VerifyItem.new:type_name -> product.VerifyParams + 22, // 5: product.VerifyItem.old:type_name -> product.VerifyParams + 4, // 6: product.Product.Create:input_type -> product.CreateReq + 5, // 7: product.Product.Info:input_type -> product.InfoReq + 6, // 8: product.Product.Items:input_type -> product.ItemsReq + 7, // 9: product.Product.Names:input_type -> product.NamesReq + 8, // 10: product.Product.Status:input_type -> product.StatusReq + 9, // 11: product.Product.Sort:input_type -> product.SortReq + 10, // 12: product.Product.Verify:input_type -> product.VerifyReq + 11, // 13: product.Product.VerifyFirst:input_type -> product.VerifyStatusReq + 11, // 14: product.Product.VerifySecond:input_type -> product.VerifyStatusReq + 12, // 15: product.Product.EditApply:input_type -> product.EditApplyReq + 14, // 16: product.Product.EditBase:input_type -> product.EditBaseReq + 15, // 17: product.Product.EditSusceptible:input_type -> product.EditSusceptibleReq + 13, // 18: product.Product.EditApplyPass:input_type -> product.EditApplyPassReq + 16, // 19: product.Product.Number:input_type -> product.NumberReq + 18, // 20: product.Product.NumberItems:input_type -> product.NumberItemsReq + 1, // 21: product.Product.InfoById:input_type -> product.InfoByIdReq + 2, // 22: product.Product.ItemsByIds:input_type -> product.ItemsByIdsReq + 19, // 23: product.Product.NumberAdd:input_type -> product.NumberAddReq + 0, // 24: product.Product.Create:output_type -> product.Response + 0, // 25: product.Product.Info:output_type -> product.Response + 0, // 26: product.Product.Items:output_type -> product.Response + 0, // 27: product.Product.Names:output_type -> product.Response + 0, // 28: product.Product.Status:output_type -> product.Response + 0, // 29: product.Product.Sort:output_type -> product.Response + 0, // 30: product.Product.Verify:output_type -> product.Response + 0, // 31: product.Product.VerifyFirst:output_type -> product.Response + 0, // 32: product.Product.VerifySecond:output_type -> product.Response + 0, // 33: product.Product.EditApply:output_type -> product.Response + 0, // 34: product.Product.EditBase:output_type -> product.Response + 0, // 35: product.Product.EditSusceptible:output_type -> product.Response + 0, // 36: product.Product.EditApplyPass:output_type -> product.Response + 26, // 37: product.Product.Number:output_type -> google.protobuf.Empty + 26, // 38: product.Product.NumberItems:output_type -> google.protobuf.Empty + 25, // 39: product.Product.InfoById:output_type -> product.Item + 3, // 40: product.Product.ItemsByIds:output_type -> product.ItemsByIdsData + 0, // 41: product.Product.NumberAdd:output_type -> product.Response + 24, // [24:42] is the sub-list for method output_type + 6, // [6:24] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_product_product_proto_init() } @@ -2324,7 +2442,7 @@ func file_product_product_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_product_product_proto_rawDesc), len(file_product_product_proto_rawDesc)), NumEnums: 0, - NumMessages: 24, + NumMessages: 26, NumExtensions: 0, NumServices: 1, }, diff --git a/rpc/product/pb/product_grpc.pb.go b/rpc/product/pb/product_grpc.pb.go index 9aec8d9..315aba0 100644 --- a/rpc/product/pb/product_grpc.pb.go +++ b/rpc/product/pb/product_grpc.pb.go @@ -8,6 +8,7 @@ package product import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" @@ -34,6 +35,7 @@ const ( Product_EditSusceptible_FullMethodName = "/product.Product/EditSusceptible" Product_EditApplyPass_FullMethodName = "/product.Product/EditApplyPass" Product_Number_FullMethodName = "/product.Product/Number" + Product_NumberItems_FullMethodName = "/product.Product/NumberItems" Product_InfoById_FullMethodName = "/product.Product/InfoById" Product_ItemsByIds_FullMethodName = "/product.Product/ItemsByIds" Product_NumberAdd_FullMethodName = "/product.Product/NumberAdd" @@ -66,6 +68,8 @@ type ProductClient interface { // 增减库存 // type: 1 增加, 2 减少 Number(ctx context.Context, in *NumberReq, opts ...grpc.CallOption) (*emptypb.Empty, error) + // 批量增减库存 + NumberItems(ctx context.Context, in *NumberItemsReq, opts ...grpc.CallOption) (*emptypb.Empty, error) InfoById(ctx context.Context, in *InfoByIdReq, opts ...grpc.CallOption) (*Item, error) ItemsByIds(ctx context.Context, in *ItemsByIdsReq, opts ...grpc.CallOption) (*ItemsByIdsData, error) // 增加库存 @@ -220,6 +224,16 @@ func (c *productClient) Number(ctx context.Context, in *NumberReq, opts ...grpc. return out, nil } +func (c *productClient) NumberItems(ctx context.Context, in *NumberItemsReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, Product_NumberItems_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *productClient) InfoById(ctx context.Context, in *InfoByIdReq, opts ...grpc.CallOption) (*Item, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(Item) @@ -277,6 +291,8 @@ type ProductServer interface { // 增减库存 // type: 1 增加, 2 减少 Number(context.Context, *NumberReq) (*emptypb.Empty, error) + // 批量增减库存(服务内按 id 排序后在同一事务中执行,防死锁) + NumberItems(context.Context, *NumberItemsReq) (*emptypb.Empty, error) InfoById(context.Context, *InfoByIdReq) (*Item, error) ItemsByIds(context.Context, *ItemsByIdsReq) (*ItemsByIdsData, error) // 增加库存 @@ -333,6 +349,9 @@ func (UnimplementedProductServer) EditApplyPass(context.Context, *EditApplyPassR func (UnimplementedProductServer) Number(context.Context, *NumberReq) (*emptypb.Empty, error) { return nil, status.Error(codes.Unimplemented, "method Number not implemented") } +func (UnimplementedProductServer) NumberItems(context.Context, *NumberItemsReq) (*emptypb.Empty, error) { + return nil, status.Error(codes.Unimplemented, "method NumberItems not implemented") +} func (UnimplementedProductServer) InfoById(context.Context, *InfoByIdReq) (*Item, error) { return nil, status.Error(codes.Unimplemented, "method InfoById not implemented") } @@ -615,6 +634,24 @@ func _Product_Number_Handler(srv interface{}, ctx context.Context, dec func(inte return interceptor(ctx, in, info, handler) } +func _Product_NumberItems_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NumberItemsReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProductServer).NumberItems(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Product_NumberItems_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProductServer).NumberItems(ctx, req.(*NumberItemsReq)) + } + return interceptor(ctx, in, info, handler) +} + func _Product_InfoById_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(InfoByIdReq) if err := dec(in); err != nil { @@ -732,6 +769,10 @@ var Product_ServiceDesc = grpc.ServiceDesc{ MethodName: "Number", Handler: _Product_Number_Handler, }, + { + MethodName: "NumberItems", + Handler: _Product_NumberItems_Handler, + }, { MethodName: "InfoById", Handler: _Product_InfoById_Handler, diff --git a/rpc/product/product.pb b/rpc/product/product.pb index 38d091aafe8c66c03a6e1ef88a7885d5a2ee2657..8d100795d868fd3047833be2356bc770a651534c 100644 GIT binary patch delta 149 zcmeC5!FX*Z;|69kri;3pS<+w+KV@9*h{c8zS!*Oc8^8Hj*AW~tvoo&Pe8TM>%j9R?9{|e{4HW sale.NameItem + 2, // 1: sale.Sale.GroupItems:input_type -> sale.GroupItemsReq + 3, // 2: sale.Sale.GroupCreate:input_type -> sale.GroupCreateReq + 1, // 3: sale.Sale.GroupNames:input_type -> sale.GroupEmptyReq + 1, // 4: sale.Sale.Types:input_type -> sale.GroupEmptyReq + 4, // 5: sale.Sale.Names:input_type -> sale.NamesReq + 4, // 6: sale.Sale.NamesInternal:input_type -> sale.NamesReq + 7, // 7: sale.Sale.Create:input_type -> sale.CreateReq + 8, // 8: sale.Sale.Edit:input_type -> sale.EditReq + 9, // 9: sale.Sale.Info:input_type -> sale.InfoReq + 10, // 10: sale.Sale.Items:input_type -> sale.ItemsReq + 11, // 11: sale.Sale.Status:input_type -> sale.StatusReq + 0, // 12: sale.Sale.GroupItems:output_type -> sale.Response + 0, // 13: sale.Sale.GroupCreate:output_type -> sale.Response + 0, // 14: sale.Sale.GroupNames:output_type -> sale.Response + 0, // 15: sale.Sale.Types:output_type -> sale.Response + 0, // 16: sale.Sale.Names:output_type -> sale.Response + 6, // 17: sale.Sale.NamesInternal:output_type -> sale.NamesData + 0, // 18: sale.Sale.Create:output_type -> sale.Response + 0, // 19: sale.Sale.Edit:output_type -> sale.Response + 0, // 20: sale.Sale.Info:output_type -> sale.Response + 0, // 21: sale.Sale.Items:output_type -> sale.Response + 0, // 22: sale.Sale.Status:output_type -> sale.Response + 12, // [12:23] is the sub-list for method output_type + 1, // [1:12] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_sale_sale_proto_init() } +func file_sale_sale_proto_init() { + if File_sale_sale_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_sale_sale_proto_rawDesc), len(file_sale_sale_proto_rawDesc)), + NumEnums: 0, + NumMessages: 12, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_sale_sale_proto_goTypes, + DependencyIndexes: file_sale_sale_proto_depIdxs, + MessageInfos: file_sale_sale_proto_msgTypes, + }.Build() + File_sale_sale_proto = out.File + file_sale_sale_proto_goTypes = nil + file_sale_sale_proto_depIdxs = nil +} diff --git a/rpc/sale/pb/sale_grpc.pb.go b/rpc/sale/pb/sale_grpc.pb.go new file mode 100644 index 0000000..0f2a681 --- /dev/null +++ b/rpc/sale/pb/sale_grpc.pb.go @@ -0,0 +1,505 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.2 +// - protoc v3.19.4 +// source: sale/sale.proto + +package sale + +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.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Sale_GroupItems_FullMethodName = "/sale.Sale/GroupItems" + Sale_GroupCreate_FullMethodName = "/sale.Sale/GroupCreate" + Sale_GroupNames_FullMethodName = "/sale.Sale/GroupNames" + Sale_Types_FullMethodName = "/sale.Sale/Types" + Sale_Names_FullMethodName = "/sale.Sale/Names" + Sale_NamesInternal_FullMethodName = "/sale.Sale/NamesInternal" + Sale_Create_FullMethodName = "/sale.Sale/Create" + Sale_Edit_FullMethodName = "/sale.Sale/Edit" + Sale_Info_FullMethodName = "/sale.Sale/Info" + Sale_Items_FullMethodName = "/sale.Sale/Items" + Sale_Status_FullMethodName = "/sale.Sale/Status" +) + +// SaleClient is the client API for Sale 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 SaleClient interface { + // 销售分组 + GroupItems(ctx context.Context, in *GroupItemsReq, opts ...grpc.CallOption) (*Response, error) + GroupCreate(ctx context.Context, in *GroupCreateReq, opts ...grpc.CallOption) (*Response, error) + GroupNames(ctx context.Context, in *GroupEmptyReq, opts ...grpc.CallOption) (*Response, error) + // 销售管理 + Types(ctx context.Context, in *GroupEmptyReq, opts ...grpc.CallOption) (*Response, error) + Names(ctx context.Context, in *NamesReq, opts ...grpc.CallOption) (*Response, error) + NamesInternal(ctx context.Context, in *NamesReq, opts ...grpc.CallOption) (*NamesData, error) + Create(ctx context.Context, in *CreateReq, opts ...grpc.CallOption) (*Response, error) + Edit(ctx context.Context, in *EditReq, opts ...grpc.CallOption) (*Response, error) + Info(ctx context.Context, in *InfoReq, opts ...grpc.CallOption) (*Response, error) + Items(ctx context.Context, in *ItemsReq, opts ...grpc.CallOption) (*Response, error) + Status(ctx context.Context, in *StatusReq, opts ...grpc.CallOption) (*Response, error) +} + +type saleClient struct { + cc grpc.ClientConnInterface +} + +func NewSaleClient(cc grpc.ClientConnInterface) SaleClient { + return &saleClient{cc} +} + +func (c *saleClient) GroupItems(ctx context.Context, in *GroupItemsReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Sale_GroupItems_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *saleClient) GroupCreate(ctx context.Context, in *GroupCreateReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Sale_GroupCreate_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *saleClient) GroupNames(ctx context.Context, in *GroupEmptyReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Sale_GroupNames_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *saleClient) Types(ctx context.Context, in *GroupEmptyReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Sale_Types_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *saleClient) Names(ctx context.Context, in *NamesReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Sale_Names_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *saleClient) NamesInternal(ctx context.Context, in *NamesReq, opts ...grpc.CallOption) (*NamesData, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(NamesData) + err := c.cc.Invoke(ctx, Sale_NamesInternal_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *saleClient) Create(ctx context.Context, in *CreateReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Sale_Create_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *saleClient) Edit(ctx context.Context, in *EditReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Sale_Edit_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *saleClient) Info(ctx context.Context, in *InfoReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Sale_Info_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *saleClient) Items(ctx context.Context, in *ItemsReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Sale_Items_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *saleClient) Status(ctx context.Context, in *StatusReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Sale_Status_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// SaleServer is the server API for Sale service. +// All implementations must embed UnimplementedSaleServer +// for forward compatibility. +type SaleServer interface { + // 销售分组 + GroupItems(context.Context, *GroupItemsReq) (*Response, error) + GroupCreate(context.Context, *GroupCreateReq) (*Response, error) + GroupNames(context.Context, *GroupEmptyReq) (*Response, error) + // 销售管理 + Types(context.Context, *GroupEmptyReq) (*Response, error) + Names(context.Context, *NamesReq) (*Response, error) + NamesInternal(context.Context, *NamesReq) (*NamesData, error) + Create(context.Context, *CreateReq) (*Response, error) + Edit(context.Context, *EditReq) (*Response, error) + Info(context.Context, *InfoReq) (*Response, error) + Items(context.Context, *ItemsReq) (*Response, error) + Status(context.Context, *StatusReq) (*Response, error) + mustEmbedUnimplementedSaleServer() +} + +// UnimplementedSaleServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedSaleServer struct{} + +func (UnimplementedSaleServer) GroupItems(context.Context, *GroupItemsReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method GroupItems not implemented") +} +func (UnimplementedSaleServer) GroupCreate(context.Context, *GroupCreateReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method GroupCreate not implemented") +} +func (UnimplementedSaleServer) GroupNames(context.Context, *GroupEmptyReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method GroupNames not implemented") +} +func (UnimplementedSaleServer) Types(context.Context, *GroupEmptyReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method Types not implemented") +} +func (UnimplementedSaleServer) Names(context.Context, *NamesReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method Names not implemented") +} +func (UnimplementedSaleServer) NamesInternal(context.Context, *NamesReq) (*NamesData, error) { + return nil, status.Error(codes.Unimplemented, "method NamesInternal not implemented") +} +func (UnimplementedSaleServer) Create(context.Context, *CreateReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method Create not implemented") +} +func (UnimplementedSaleServer) Edit(context.Context, *EditReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method Edit not implemented") +} +func (UnimplementedSaleServer) Info(context.Context, *InfoReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method Info not implemented") +} +func (UnimplementedSaleServer) Items(context.Context, *ItemsReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method Items not implemented") +} +func (UnimplementedSaleServer) Status(context.Context, *StatusReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method Status not implemented") +} +func (UnimplementedSaleServer) mustEmbedUnimplementedSaleServer() {} +func (UnimplementedSaleServer) testEmbeddedByValue() {} + +// UnsafeSaleServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to SaleServer will +// result in compilation errors. +type UnsafeSaleServer interface { + mustEmbedUnimplementedSaleServer() +} + +func RegisterSaleServer(s grpc.ServiceRegistrar, srv SaleServer) { + // If the following call panics, it indicates UnimplementedSaleServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Sale_ServiceDesc, srv) +} + +func _Sale_GroupItems_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GroupItemsReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SaleServer).GroupItems(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sale_GroupItems_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SaleServer).GroupItems(ctx, req.(*GroupItemsReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Sale_GroupCreate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GroupCreateReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SaleServer).GroupCreate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sale_GroupCreate_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SaleServer).GroupCreate(ctx, req.(*GroupCreateReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Sale_GroupNames_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GroupEmptyReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SaleServer).GroupNames(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sale_GroupNames_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SaleServer).GroupNames(ctx, req.(*GroupEmptyReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Sale_Types_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GroupEmptyReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SaleServer).Types(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sale_Types_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SaleServer).Types(ctx, req.(*GroupEmptyReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Sale_Names_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NamesReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SaleServer).Names(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sale_Names_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SaleServer).Names(ctx, req.(*NamesReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Sale_NamesInternal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NamesReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SaleServer).NamesInternal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sale_NamesInternal_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SaleServer).NamesInternal(ctx, req.(*NamesReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Sale_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SaleServer).Create(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sale_Create_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SaleServer).Create(ctx, req.(*CreateReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Sale_Edit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EditReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SaleServer).Edit(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sale_Edit_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SaleServer).Edit(ctx, req.(*EditReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Sale_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InfoReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SaleServer).Info(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sale_Info_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SaleServer).Info(ctx, req.(*InfoReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Sale_Items_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ItemsReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SaleServer).Items(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sale_Items_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SaleServer).Items(ctx, req.(*ItemsReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Sale_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StatusReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SaleServer).Status(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sale_Status_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SaleServer).Status(ctx, req.(*StatusReq)) + } + return interceptor(ctx, in, info, handler) +} + +// Sale_ServiceDesc is the grpc.ServiceDesc for Sale service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Sale_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "sale.Sale", + HandlerType: (*SaleServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GroupItems", + Handler: _Sale_GroupItems_Handler, + }, + { + MethodName: "GroupCreate", + Handler: _Sale_GroupCreate_Handler, + }, + { + MethodName: "GroupNames", + Handler: _Sale_GroupNames_Handler, + }, + { + MethodName: "Types", + Handler: _Sale_Types_Handler, + }, + { + MethodName: "Names", + Handler: _Sale_Names_Handler, + }, + { + MethodName: "NamesInternal", + Handler: _Sale_NamesInternal_Handler, + }, + { + MethodName: "Create", + Handler: _Sale_Create_Handler, + }, + { + MethodName: "Edit", + Handler: _Sale_Edit_Handler, + }, + { + MethodName: "Info", + Handler: _Sale_Info_Handler, + }, + { + MethodName: "Items", + Handler: _Sale_Items_Handler, + }, + { + MethodName: "Status", + Handler: _Sale_Status_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "sale/sale.proto", +} diff --git a/rpc/sale/sale.pb b/rpc/sale/sale.pb new file mode 100644 index 0000000000000000000000000000000000000000..767894e4751b0990b20b2e75f7b38bc8beb7c952 GIT binary patch literal 16510 zcmeHOU2J2=bv8*+B1aN+HPY_VTsym_|JLi6ifJdd*Fh3Wy3%q@k?JM2-ZfefSLBtJ zHbpYLu!iy%69O2*E<9rBI|PE**`#-P2~cxnQFcxPxh1n=z75VJC!5r8-InJ?a$t{I zce3-kLp9|qV!kzYNBxs*3LT5Z$HU6l;vSNF-yV&eVGpBgbO<$f*l(X^7l@z5zvYu+ z8TuLYd#=;u&L!?#@_?HlfJWEscDplz>g;awu+wXIddF^d@jh!I1A^oPeA z$4-xJYeRLxvRt-0yVvWFY?_z*dg%8@@wwg7e)({oiCz+)9E!_|a)Tj<ihjeSvCge`>|;kSo7a?|5u)u3oL<}MwN9}+60pM%L_RN82jjzT zrv`kCP4=su-cdiB zW*2lR!l2HGTkyYSpjjD3=(XY7=H1iY$bK)Y{EcqOqF8X0qseB#IaAC=IGd{9@(}ZX zHZNADW;@d?Ul++E(hQ99A@rtbCKaz%@8K0+5{o^@9U&C49g_W@#SVocikhJ^@Sl0pwjvJuhslv)eEKd^|*%J_V^Ew_c}_niI_McyuKYqpwegfhk1N;4s1 zaaX<;m?uT5#bVUD_SANcSm=Ss_|aa?EX_g`9yl{E{;P>mOyrzF%}WJIl|-<&BbSu6 zC`dA}3a^)YUt}iLgMgoONA_^U&M|4JhBQP14v;-#(xRX8E5U>*VOT6a6A^ck^YpxP zuZZP|37mE4{9n(Bb2E9%TVj3O>+}$<2Sa2h?WS@W*-w<$i5lHO7+Xnbtxd2{KzUm% zl6}}i4!n9d7SA^20$GTr+)R8c7PrE@kQ$|q9D6jz!eooA%8L=cI|>2O&GM1uiCDVp z3_C}imJ*8AAya%cLOfGfg_|MLI`RqUnmDN5G_CSZ+1yrQPO#7YR!l60WPHL4*YPi&|EqbiJ}dgn^vA)Z zN!!7sOCs5|51lS2%9-Nxkwus_LZLz=mZFqj(yF19I#axQHV))pEmkS%oz$uH&gr+6 zA^__hI(8@qw;eCP@!OP6x1A$<+#NOV+TF3EbL}M!yh$*5Nh~TiiDcJ#k3(qEQl7I+ z5E}k%x8GC43$^S7;Nf2hyv0=hAIc#S=BAwlV< zNEx*BjobTXbGvr1Suu?mEji2Lnwwef|Qjf78dpa64WgqMm&63%Z)F(}_M zw?Q&L2?5T6To!4@*{sznM#|?|Z&>B(u95b6?pn2jeM9&h_RM;{v}+oRKE~$lhFLe3 zd=?}YhFJE8Fslc9MnbC55Kq_Sm|H$4~GO~i;Tdpf8qx^TX!;#)M|Bo@;`%3q2^bCvLXVWtFAgBOV9 zL{PLI6xAsUnvUu?s74r_IlBI8Ol0q+oSCW)Tp}%J;1XXC_Po;I6Eju7i!iOm{10N{ z{OohZOc}l;=1-i_oxYbRN0X5~?w-=OrK!T{o02t}zG-P9l72fb&dp>#Q_#nS==4xn zQOUH5j%kLl^CB-h9{K$w3l5tK#0akjN~My_V(~K(r7B^j<&>WjMyuO#dZVU08anm~ zsv#=cUP~U?UDvTzRCnF$B??Xzhan1zD=D8sb^8?gAEw139k})2@(Ho@wtd%bdM9gj z;9exyzB+7Ukab4E9Gzhkd6MgL;y_^{ZAt2@QP-B&BR?rq17)p#bOm3r;# zK$6$QdFBEgLV?ZJ9jEn9b38hFHG45UK1&F_0B4I(4uB!+VyTbg=}G5($c&mC9YZt4 zsA~#out1t5f;}8cuO;jIrnzk`dR%t;LkWXA?)wT}1k1FQKJI(!g|b?$CeIlK3R*9m zmVe+Qwb%hjW3l!h{@rz4hl=PLpE9!D)0vIWgkkbeimGuCfdr)@;UH!@7Tiu=P)je*2zAtP!*g~83vPKyYF_6Mjpp!8Euhan%fm& z4DJjj2fo5+8NkEiBL5;xGJ7@XbBwkGU@+p#;yfY2%h_#vWQVXn%h>Da#m?u>fC_RB z$A_oBeY~LLB$#I*KlSnBQ#)+suZg9w-OIF4mXCx4dDd2K+icd$Z<)yDkeXG>4YO$- zR2$_z(@2C8dz=rh8qeeJGsd$PsV8ET`TtIc%;d3LeoZ#J;XQ%O`@|k#Q;deHPL4wo04BBNP4P^yeVSe8*lwLRIZ@}j5~^aoBh)TOR2ldD zUp}CyFu@Jv@qB>U@~|gPtyB(MES~Yy`l*@C&^Y}Y&EZ}d-NaJtX5c%&d zizS{8SsBXcsFNmJbX4M^N2d5>B&LS33tJS4ug$C6-cpow8ivDo2fm9J*wQVzE9T#J znKy;bOfg!6nBaY*&dk#{>dk7++ACEoO)ei5b6xxW)5)04AUMU9aZi;3Q1f7{m9Vj7 zg5C;PoYk%{A{C`4BP)aC6@k;?;rJN$RBgL8nv5r?ZlKHJ9{GkyQz@oLisqwRruf4B z)vFf8@`$W}US1aqs7>Ln%FV7J@68mWHL?k9Dpn09A-!52xqMR?x@L<_%4c5}2>{jp zK6`)ZbR~CN5m_smi*CCU`{LZg?27}jqRT){cRU#MQGz?q^bZioD-9_cE2EjzRr}K` ziRIox?NF7q_2k2aaB@~>DTLFp#5<@_P*#oHZ^uPua$?v>(pxc9_=f%VxP{F|8Rh-P zS=BUUpCrsE@N>Lt&%$Us$VE29n#Taf-F(*`qMCTD?oTZl>UvZ4z|DB(f_-z+$Mvo* z7v1~9Afx5C6n=g~B-#B)A+!TRaVsU}wrbWk!Xx6La!bwqvblu_ng6_)S3ZS8r|(rj zq?)=w!GV=}5B4@q3uLgyseLHViB-#Nm?4wQwR<+Otfb< zuGhAW^sI;_jkWwA#gG8eg@aPnq*Eb_|CtK5`M-;c#ZWDTN`-c}+kdxdcRNVWRXh|7 zDiP$Y@#pNR3!h5)==QLwi@L1&*-BlIwB-L08^y1}cxEt}50W9w%m>36Jt_ap)-oN{ zCo;~7s6HcDsdB{6Xs`L*AYmCH z_KY@>B|Z5t3jfqJnco-2^lZqX&zKK_-kMmc)^G^LNz~lgF}E6ZbwO^j#I6zFunj~iNxNvUc9^&-DM>Y#w8aw*!lC~yRDF0#tc3W>*D zcoKEjX(ETx$h2|i@KiI`K?N=Zf>&}X*pNhH>J%e zDGt?DQU%n|rw4SL-DZj}Mh{8B;Fcz3m6)1v^M!k;q*UG3vOu!^($*VjL7H=(025r~ z*KpKDEtQO{gE|-;D#?Cl-j@avQTY{iqbamf!m9%{RFU_wN+1SbgWo1GGBjF1it!Dv zJmjlHUD!TL9?T<@-@qljs@`zHiSNWS zGu~bV_FUlN4P$S<#=|B)jD-#2f|M0=w*-H^Y1SL$&uW&kQ6ZD1N~QKDDMHYws>+rB zMX}7Q;+rRuVos(>_Bvd@>A8Nm$|d0&K71rvp4lT)ha1&HTc*BCOym)aJ@cj1oHOjH zg8>daWVPUjW010DoLO#)b2Cj37u=V;`^%=16EfDeaWfl|6P%RwDJij8*)qYmEHaY@ z1dns!pt196^Jb}1-sUF;lZ=%8V1f{o?8->w=Tb2vmamJIDN~S-iL5@M;2aT=iZwK0 z77!0dw{5dh-b3Y+E?=(;5v(!AtQ&QlhOmlzrAA0DR8e^~!2sux=#nF1eGsE(5g$}@ z--yY_@l!4o28V^#V31p(A6tWgwkua&O8wh{Oc9hW3UUVhx`AIl!o}3TFUWZUANO+^ z`hU0YcRrc=wW<^Zo@H&;xuQPHoD(x{ggz5moe)6Xam7F8-`& z_?8CK8{yH=?sO+`DR8AN!|U*ouZc%JzHQv-;Eu5!3_#B~)7Axzu&w(&+NL}Gw zc{Q5jM(7G9|Ao61Vvzffm=HnNJ(mmR2R$pg80PW=?$8y8u2!k!c<3B=dc0V8;>Zn@ z&iIKVEsB2PXwml*CpJ>+7FXRf#polB`w3sDYij!LLh;F85h)Mq2Zu-Gf=JZO1{^c{ z=yItJU;Kl(Sn#|DqJX(wo+`Ypq5i6Y%9$JATtGzif%{giQ7an%8U?;&e6oPYLQ5Wb z@pHwO;8>?XFB|aih$bG^i%mRCYBX!r%56v*>L`Xf;<%8$;8DDWf3Ji(zxNyS)7`Iz zy1yUoel67fd+1(6rAg0uuXM}!3H~i?ehqir!KW48Bce?sxKZQ4;$Dxv^+NPB3lD#T zE@|A*ClZ6hAID-J#S^>xn|~P3?eb?oDn!wz3zl<4pVlA&6~7-BkLfQh=&PW>ygTfV2jBF{f1GCa%{p4p5X&6W7e?GF~7N?t5?5Z36H{Ak$k>Cet^FmG=G zwnHF#{5!yVpm+O2by0$Iz1ODib#SHLAA^#zjI`x7$rfC^P^ALIvPC~}b(%V+b#Fp7 zRCGvK3*0WZ>G{lIXE?gkgt0jMWeJ|oFa%m~;N=!*-b6^RbrRM*H9-eM;T5A-M=%s# zF_aqcP-)n~=T)afK^N)?Yte^+>}iqlo9d;k`jlkZhmwY=f)2NIw}aXPF6Zl$5gMfev3(6~WU*)mm%iFYtj}Qoqz0czk zCyhv~`RW#7RDret332k+XX%lT&uLo^%1hO5qclRdwrZ(VQ(i`KMjOE)F3{UP>X3h&8FiGq528-UEs=3X-4eM(&n>|# z<3ZAB>}r>&TY0?9pzl7$9D!zR7)_*v(nJ(b;O3+1}Q&a@3oU)yohfOrK#{FUyNFW!<2qbxGo?NH!>+JR8@0YJlPj^DB#_ zk}?#CY2hLQ-jkIt+ULYFvqI?}Up3oZIn8n-y_KG0{jBF#ru0KP z!DR;>XymfuPrql)K(olrVzDFUXqR~`^p1-t;Sx*ns9c|tVxt3M5(OVUCTj#s@!sZ3= ?", id, n). Update("number", gorm.Expr("number - ?", n)) return ret.RowsAffected, ret.Error diff --git a/services/product/internal/server/productserver.go b/services/product/internal/server/productserver.go index eae7bcc..be62e49 100644 --- a/services/product/internal/server/productserver.go +++ b/services/product/internal/server/productserver.go @@ -102,6 +102,12 @@ func (s *ProductServer) Number(ctx context.Context, in *product.NumberReq) (*emp return l.Number(in) } +// 批量增减库存(服务内按 id 排序后在同一事务中执行,防死锁) +func (s *ProductServer) NumberItems(ctx context.Context, in *product.NumberItemsReq) (*emptypb.Empty, error) { + l := logic.NewNumberItemsLogic(ctx, s.svcCtx) + return l.NumberItems(in) +} + func (s *ProductServer) InfoById(ctx context.Context, in *product.InfoByIdReq) (*product.Item, error) { l := logic.NewInfoByIdLogic(ctx, s.svcCtx) return l.InfoById(in) diff --git a/services/product/productClient/product.go b/services/product/productClient/product.go index 4c1ac92..9a52541 100644 --- a/services/product/productClient/product.go +++ b/services/product/productClient/product.go @@ -31,6 +31,8 @@ type ( NameItem = product.NameItem NamesReq = product.NamesReq NumberAddReq = product.NumberAddReq + NumberItem = product.NumberItem + NumberItemsReq = product.NumberItemsReq NumberReq = product.NumberReq Response = product.Response SortReq = product.SortReq @@ -64,6 +66,8 @@ type ( EditApplyPass(ctx context.Context, in *EditApplyPassReq, opts ...grpc.CallOption) (*Response, error) // 增减库存 Number(ctx context.Context, in *NumberReq, opts ...grpc.CallOption) (*emptypb.Empty, error) + // 批量增减库存(服务内按 id 排序后在同一事务中执行,防死锁) + NumberItems(ctx context.Context, in *NumberItemsReq, opts ...grpc.CallOption) (*emptypb.Empty, error) InfoById(ctx context.Context, in *InfoByIdReq, opts ...grpc.CallOption) (*Item, error) ItemsByIds(ctx context.Context, in *ItemsByIdsReq, opts ...grpc.CallOption) (*ItemsByIdsData, error) // 增加库存 @@ -159,6 +163,12 @@ func (m *defaultProduct) Number(ctx context.Context, in *NumberReq, opts ...grpc return client.Number(ctx, in, opts...) } +// 批量增减库存(服务内按 id 排序后在同一事务中执行,防死锁) +func (m *defaultProduct) NumberItems(ctx context.Context, in *NumberItemsReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { + client := product.NewProductClient(m.cli.Conn()) + return client.NumberItems(ctx, in, opts...) +} + func (m *defaultProduct) InfoById(ctx context.Context, in *InfoByIdReq, opts ...grpc.CallOption) (*Item, error) { client := product.NewProductClient(m.cli.Conn()) return client.InfoById(ctx, in, opts...) diff --git a/services/product/validator/validator.go b/services/product/validator/validator.go index e4bdc8c..1fd3c3c 100644 --- a/services/product/validator/validator.go +++ b/services/product/validator/validator.go @@ -252,6 +252,17 @@ func (p ProductNumberAddValidator) GetMessage() validate.ValidatorMessages { } } +type ProductNumberItemsValidator struct { + Type uint32 `validate:"required,oneof=1 2"` +} + +func (p ProductNumberItemsValidator) GetMessage() validate.ValidatorMessages { + return validate.ValidatorMessages{ + "Type.required": "类型不能为空", + "Type.oneof": "类型不对", + } +} + type ProductItemsByIdsValidator struct { Ids []int64 `validate:"required,min=1"` } diff --git a/services/sale/.gitignore b/services/sale/.gitignore new file mode 100644 index 0000000..d05f1c7 --- /dev/null +++ b/services/sale/.gitignore @@ -0,0 +1,2 @@ +services/sale/logs/ +services/sale/run.toml diff --git a/services/sale/Dockerfile b/services/sale/Dockerfile new file mode 100644 index 0000000..39eb372 --- /dev/null +++ b/services/sale/Dockerfile @@ -0,0 +1,39 @@ +FROM golang:1.26.5-alpine AS builder + +WORKDIR /src + +ENV GOPROXY=https://goproxy.cn,direct \ + CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 + +COPY pkg ./pkg +COPY go.mod go.sum ./ + +RUN --mount=type=cache,target=/go/pkg/mod \ + go mod download + +COPY rpc/ ./rpc +COPY services/sale/ ./services/sale/ + +WORKDIR /src/services/sale + +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + go build -ldflags="-s -w" -o /out/main ./ + +FROM alpine:3.22 + +WORKDIR /app + +ENV TZ=Asia/Shanghai + +RUN apk add --no-cache tzdata \ + && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ + && echo "Asia/Shanghai" > /etc/timezone + +COPY --from=builder /out/main . + +EXPOSE 10500 + +CMD ["./main", "-f", "etc/sale.yaml"] diff --git a/services/sale/etc/sale.yaml b/services/sale/etc/sale.yaml new file mode 100644 index 0000000..98c1249 --- /dev/null +++ b/services/sale/etc/sale.yaml @@ -0,0 +1,7 @@ +Nacos: + Hosts: + - rnacos:8848 + NamespaceId: test + Group: LONE_SERVICES + RegisterIP: sale + ConfigID: sale diff --git a/services/sale/internal/config/config.go b/services/sale/internal/config/config.go new file mode 100644 index 0000000..a1979dd --- /dev/null +++ b/services/sale/internal/config/config.go @@ -0,0 +1,13 @@ +package config + +type Config struct { + Nacos NacosConf +} + +type NacosConf struct { + Hosts []string + NamespaceId string `json:",optional"` + Group string `json:",optional"` + RegisterIP string `json:",optional"` + ConfigID string `json:",optional"` +} diff --git a/services/sale/internal/dao/sale.go b/services/sale/internal/dao/sale.go new file mode 100644 index 0000000..db8bbfc --- /dev/null +++ b/services/sale/internal/dao/sale.go @@ -0,0 +1,131 @@ +package dao + +import ( + "database/sql/driver" + "encoding/json" + "fmt" + + "lone-services/pkg/utils" +) + +const ( + SaleTypeStaff uint8 = 1 // 销售人员 + SaleTypeAgentCorp uint8 = 2 // 销售商(法人) + SaleTypeAgentPerson uint8 = 3 // 销售商(个人) + + SaleStatusPending uint8 = 9 // 待处理 + SaleStatusApproved uint8 = 1 // 已通过 + SaleStatusRejected uint8 = 2 // 未通过 + SaleStatusDisabled uint8 = 3 // 禁用 +) + +type RegionNames struct { + Province string `json:"province"` + City string `json:"city"` + District string `json:"district"` +} + +func (r RegionNames) Value() (driver.Value, error) { + buf, err := json.Marshal(r) + if err != nil { + return nil, err + } + return string(buf), nil +} + +func (r *RegionNames) Scan(value interface{}) error { + if value == nil { + *r = RegionNames{} + return nil + } + var raw []byte + switch v := value.(type) { + case []byte: + raw = v + case string: + raw = []byte(v) + default: + return fmt.Errorf("unsupported region type: %T", value) + } + if len(raw) == 0 { + *r = RegionNames{} + return nil + } + return json.Unmarshal(raw, r) +} + +type SaleCreate struct { + Id int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` + SaleId int64 `gorm:"column:sale_id" json:"sale_id"` + Mobile string `gorm:"column:mobile" json:"mobile"` + Name string `gorm:"column:name" json:"name"` + IdCardFront string `gorm:"column:id_card_front" json:"id_card_front"` + IdCardBack string `gorm:"column:id_card_back" json:"id_card_back"` + BusinessLicense string `gorm:"column:business_license" json:"business_license"` + Region RegionNames `gorm:"column:region;type:json" json:"region"` + ProvinceId int64 `gorm:"column:province_id" json:"province_id"` + CityId int64 `gorm:"column:city_id" json:"city_id"` + DistrictId int64 `gorm:"column:district_id" json:"district_id"` + TerritoryId int64 `gorm:"column:territory_id" json:"territory_id"` + TerritoryName string `gorm:"column:territory_name" json:"territory_name"` + GroupId int64 `gorm:"column:group_id" json:"group_id"` + Address string `gorm:"column:address" json:"address"` + Status uint8 `gorm:"column:status" json:"status"` + Avatar string `gorm:"column:avatar" json:"avatar"` + Account string `gorm:"column:account" json:"account"` + Type uint8 `gorm:"column:type" json:"type"` + Sex uint8 `gorm:"column:sex" json:"sex"` + BirthDate string `gorm:"column:birth_date" json:"birth_date"` + AdminId int64 `gorm:"column:admin_id" json:"admin_id"` + AdminName string `gorm:"column:admin_name" json:"admin_name"` +} + +type SaleInfo struct { + Id int64 `gorm:"column:id" json:"id"` + SaleId int64 `gorm:"column:sale_id" json:"sale_id"` + Mobile string `gorm:"column:mobile" json:"mobile"` + Name string `gorm:"column:name" json:"name"` + IdCardFront string `gorm:"column:id_card_front" json:"id_card_front"` + IdCardBack string `gorm:"column:id_card_back" json:"id_card_back"` + BusinessLicense string `gorm:"column:business_license" json:"business_license"` + Region RegionNames `gorm:"column:region;type:json" json:"region"` + ProvinceId int64 `gorm:"column:province_id" json:"province_id"` + CityId int64 `gorm:"column:city_id" json:"city_id"` + DistrictId int64 `gorm:"column:district_id" json:"district_id"` + TerritoryId int64 `gorm:"column:territory_id" json:"territory_id"` + TerritoryName string `gorm:"column:territory_name" json:"territory_name"` + GroupId int64 `gorm:"column:group_id" json:"group_id"` + Address string `gorm:"column:address" json:"address"` + Status uint8 `gorm:"column:status" json:"status"` + Avatar string `gorm:"column:avatar" json:"avatar"` + Account string `gorm:"column:account" json:"account"` + Type uint8 `gorm:"column:type" json:"type"` + Sex uint8 `gorm:"column:sex" json:"sex"` + BirthDate string `gorm:"column:birth_date" json:"birth_date"` + Reason string `gorm:"column:reason" json:"reason"` + AdminId int64 `gorm:"column:admin_id" json:"admin_id"` + AdminName string `gorm:"column:admin_name" json:"admin_name"` + CreateTime utils.CustomTime `gorm:"column:create_time" json:"create_time"` + UpdateTime utils.CustomTime `gorm:"column:update_time" json:"update_time"` + OriginMobile string `gorm:"-" json:"origin_mobile"` +} + +type SaleStatusUpdate struct { + Id int64 `gorm:"column:id;primaryKey" json:"id"` + Name string `gorm:"column:name" json:"name"` + Status uint8 `gorm:"column:status" json:"status"` + Reason string `gorm:"column:reason" json:"reason"` + AdminId int64 `gorm:"column:admin_id" json:"admin_id"` + AdminName string `gorm:"column:admin_name" json:"admin_name"` +} + +type SaleNameItem struct { + Id int64 `gorm:"column:id" json:"id"` + Mobile string `gorm:"column:mobile" json:"mobile"` + Name string `gorm:"column:name" json:"name"` +} + +type SaleTypeOption struct { + Value uint8 `json:"value"` + Label string `json:"label"` +} diff --git a/services/sale/internal/dao/sale_group.go b/services/sale/internal/dao/sale_group.go new file mode 100644 index 0000000..05f8727 --- /dev/null +++ b/services/sale/internal/dao/sale_group.go @@ -0,0 +1,22 @@ +package dao + +import "lone-services/pkg/utils" + +type SaleGroup struct { + Id int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` + Name string `gorm:"column:name" json:"name"` + CreatedAt utils.CustomTime `gorm:"column:created_at" json:"created_at"` + UpdatedAt utils.CustomTime `gorm:"column:updated_at" json:"updated_at"` +} + +type SaleGroupCreate struct { + Id int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` + Name string `gorm:"column:name" json:"name"` + CreatedAt utils.CustomTime `gorm:"column:created_at" json:"created_at"` + UpdatedAt utils.CustomTime `gorm:"column:updated_at" json:"updated_at"` +} + +type SaleGroupNameItem struct { + Id int64 `json:"id"` + Name string `json:"name"` +} diff --git a/services/sale/internal/logic/createLogic.go b/services/sale/internal/logic/createLogic.go new file mode 100644 index 0000000..394a772 --- /dev/null +++ b/services/sale/internal/logic/createLogic.go @@ -0,0 +1,91 @@ +package logic + +import ( + "context" + + "lone-services/pkg/modelbase" + "lone-services/pkg/utils" + "lone-services/pkg/validate" + sale "lone-services/rpc/sale/pb" + "lone-services/services/sale/internal/dao" + "lone-services/services/sale/internal/model" + "lone-services/services/sale/internal/svc" + "lone-services/services/sale/validator" + + "github.com/zeromicro/go-zero/core/logx" +) + +type CreateLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewCreateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateLogic { + return &CreateLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *CreateLogic) Create(in *sale.CreateReq) (*sale.Response, error) { + var req validator.CreateValidator + if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { + return outResponse(utils.ErrorParams, msg), nil + } + if msg := validateSaleTypeRules(req.Type, req.Account, req.BusinessLicense); msg != utils.StringEmpty { + return outResponse(utils.ErrorParams, msg), nil + } + + adminInfo := utils.GetUserFromCtx(l.ctx) + if adminInfo.ID < utils.NumberOne { + return failResponse(utils.ErrorNoLoginInfo), nil + } + + encryptMobile, err := utils.EncryptPhone(req.Mobile) + if err != nil { + l.Errorf("encrypt mobile: %v", err) + return failResponse(utils.Fail), nil + } + + m := model.SaleModel{}.Init() + var existing dao.SaleStatusUpdate + if err := m.GetOne(modelbase.Params{Eq: map[string]string{"mobile": encryptMobile}}, &existing); err != nil { + l.Errorf("sale create check: %v", err) + return failResponse(utils.Fail), nil + } + if existing.Id > utils.NumberZero { + return failResponse(utils.ErrorDataIsExist), nil + } + + data := dao.SaleCreate{ + SaleId: req.SaleId, + Mobile: encryptMobile, + Name: req.Name, + IdCardFront: req.IdCardFront, + IdCardBack: req.IdCardBack, + BusinessLicense: req.BusinessLicense, + Region: buildRegion(req.RegionProvince, req.RegionCity, req.RegionDistrict), + ProvinceId: req.ProvinceId, + CityId: req.CityId, + DistrictId: req.DistrictId, + TerritoryId: req.TerritoryId, + TerritoryName: req.TerritoryName, + GroupId: req.GroupId, + Address: req.Address, + Status: dao.SaleStatusApproved, + Account: req.Account, + Type: uint8(req.Type), + Sex: uint8(req.Sex), + BirthDate: req.BirthDate, + AdminId: adminInfo.ID, + AdminName: adminInfo.Name, + } + if err := m.Create(&data); err != nil { + l.Errorf("sale create: %v", err) + return failResponse(utils.Fail), nil + } + + return okResponse(nil), nil +} diff --git a/services/sale/internal/logic/editLogic.go b/services/sale/internal/logic/editLogic.go new file mode 100644 index 0000000..de63da2 --- /dev/null +++ b/services/sale/internal/logic/editLogic.go @@ -0,0 +1,97 @@ +package logic + +import ( + "context" + "strconv" + + "lone-services/pkg/modelbase" + "lone-services/pkg/utils" + "lone-services/pkg/validate" + sale "lone-services/rpc/sale/pb" + "lone-services/services/sale/internal/dao" + "lone-services/services/sale/internal/model" + "lone-services/services/sale/internal/svc" + "lone-services/services/sale/validator" + + "github.com/zeromicro/go-zero/core/logx" +) + +type EditLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewEditLogic(ctx context.Context, svcCtx *svc.ServiceContext) *EditLogic { + return &EditLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *EditLogic) Edit(in *sale.EditReq) (*sale.Response, error) { + var req validator.EditValidator + if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { + return outResponse(utils.ErrorParams, msg), nil + } + if msg := validateSaleTypeRules(req.Type, req.Account, req.BusinessLicense); msg != utils.StringEmpty { + return outResponse(utils.ErrorParams, msg), nil + } + + adminInfo := utils.GetUserFromCtx(l.ctx) + if adminInfo.ID < utils.NumberOne { + return failResponse(utils.ErrorNoLoginInfo), nil + } + + w := modelbase.Params{Eq: map[string]string{"id": strconv.FormatInt(req.Id, 10)}} + m := model.SaleModel{}.Init() + var info dao.SaleCreate + if err := m.GetOne(w, &info); err != nil || info.Id < utils.NumberOne { + return failResponse(utils.ErrorNotFund), nil + } + + encryptMobile, err := utils.EncryptPhone(req.Mobile) + if err != nil { + l.Errorf("encrypt mobile: %v", err) + return failResponse(utils.Fail), nil + } + if encryptMobile != info.Mobile { + var check dao.SaleStatusUpdate + if err := m.GetOne(modelbase.Params{Eq: map[string]string{"mobile": encryptMobile}}, &check); err != nil { + l.Errorf("sale edit mobile check: %v", err) + return failResponse(utils.Fail), nil + } + if check.Id > utils.NumberZero && check.Id != req.Id { + return failResponse(utils.ErrorDataIsExist), nil + } + } + + info.SaleId = req.SaleId + info.Mobile = encryptMobile + info.Name = req.Name + info.IdCardFront = req.IdCardFront + info.IdCardBack = req.IdCardBack + info.BusinessLicense = req.BusinessLicense + info.Region = buildRegion(req.RegionProvince, req.RegionCity, req.RegionDistrict) + info.ProvinceId = req.ProvinceId + info.CityId = req.CityId + info.DistrictId = req.DistrictId + info.TerritoryId = req.TerritoryId + info.TerritoryName = req.TerritoryName + info.GroupId = req.GroupId + info.Address = req.Address + info.Type = uint8(req.Type) + info.Sex = uint8(req.Sex) + info.BirthDate = req.BirthDate + info.Account = req.Account + info.AdminId = adminInfo.ID + info.AdminName = adminInfo.Name + + if _, err := m.Edit(w, &info); err != nil { + l.Errorf("sale edit: %v", err) + return failResponse(utils.Fail), nil + } + + return okStringResponse(utils.StringEmpty), nil +} diff --git a/services/sale/internal/logic/groupCreateLogic.go b/services/sale/internal/logic/groupCreateLogic.go new file mode 100644 index 0000000..99463eb --- /dev/null +++ b/services/sale/internal/logic/groupCreateLogic.go @@ -0,0 +1,65 @@ +package logic + +import ( + "context" + + "lone-services/pkg/modelbase" + "lone-services/pkg/utils" + "lone-services/pkg/validate" + sale "lone-services/rpc/sale/pb" + "lone-services/services/sale/internal/dao" + "lone-services/services/sale/internal/model" + "lone-services/services/sale/internal/svc" + "lone-services/services/sale/validator" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GroupCreateLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewGroupCreateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GroupCreateLogic { + return &GroupCreateLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *GroupCreateLogic) GroupCreate(in *sale.GroupCreateReq) (*sale.Response, error) { + var req validator.GroupCreateValidator + if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { + return outResponse(utils.ErrorParams, msg), nil + } + + adminInfo := utils.GetUserFromCtx(l.ctx) + if adminInfo.ID < utils.NumberOne { + return failResponse(utils.ErrorNoLoginInfo), nil + } + + m := model.SaleGroupModel{}.Init() + var existing dao.SaleGroup + if err := m.GetOne(modelbase.Params{Eq: map[string]string{"name": req.Name}}, &existing); err != nil { + l.Errorf("group create check: %v", err) + return failResponse(utils.Fail), nil + } + if existing.Id > utils.NumberZero { + return failResponse(utils.ErrorDataIsExist), nil + } + + now := utils.Now() + data := dao.SaleGroupCreate{ + Name: req.Name, + CreatedAt: now, + UpdatedAt: now, + } + if err := m.Create(&data); err != nil { + l.Errorf("group create: %v", err) + return failResponse(utils.Fail), nil + } + + return okResponse(nil), nil +} diff --git a/services/sale/internal/logic/groupItemsLogic.go b/services/sale/internal/logic/groupItemsLogic.go new file mode 100644 index 0000000..7cb0356 --- /dev/null +++ b/services/sale/internal/logic/groupItemsLogic.go @@ -0,0 +1,68 @@ +package logic + +import ( + "context" + + "lone-services/pkg/modelbase" + "lone-services/pkg/utils" + "lone-services/pkg/validate" + sale "lone-services/rpc/sale/pb" + "lone-services/services/sale/internal/dao" + "lone-services/services/sale/internal/model" + "lone-services/services/sale/internal/svc" + "lone-services/services/sale/validator" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GroupItemsLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewGroupItemsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GroupItemsLogic { + return &GroupItemsLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *GroupItemsLogic) GroupItems(in *sale.GroupItemsReq) (*sale.Response, error) { + var req validator.GroupItemsValidator + if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { + return outResponse(utils.ErrorParams, msg), nil + } + + page := int(req.Page) + size := int(req.PageSize) + if page < modelbase.DefaultPage { + page = modelbase.DefaultPage + } + if size < modelbase.DefaultPage { + size = modelbase.DefaultSize + } + + w := modelbase.Params{ + Page: page, + Size: size, + Order: "id desc", + Like: map[string]string{}, + } + if req.Name != utils.StringEmpty { + w.Like["name LIKE ?"] = "%" + req.Name + "%" + } + + var list []dao.SaleGroup + result, err := model.SaleGroupModel{}.Init().Page(w, &list) + if err != nil { + l.Errorf("group items: %v", err) + return failResponse(utils.Fail), nil + } + + return okResponse(map[string]any{ + "count": result.Count, + "items": list, + }), nil +} diff --git a/services/sale/internal/logic/groupNamesLogic.go b/services/sale/internal/logic/groupNamesLogic.go new file mode 100644 index 0000000..352ac01 --- /dev/null +++ b/services/sale/internal/logic/groupNamesLogic.go @@ -0,0 +1,41 @@ +package logic + +import ( + "context" + + "lone-services/pkg/modelbase" + "lone-services/pkg/utils" + "lone-services/services/sale/internal/dao" + "lone-services/services/sale/internal/model" + "lone-services/services/sale/internal/svc" + + sale "lone-services/rpc/sale/pb" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GroupNamesLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewGroupNamesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GroupNamesLogic { + return &GroupNamesLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *GroupNamesLogic) GroupNames(_ *sale.GroupEmptyReq) (*sale.Response, error) { + var list []dao.SaleGroupNameItem + if err := (model.SaleGroupModel{}.Init().Items(modelbase.Params{Order: "id ASC"}, &list)); err != nil { + l.Errorf("group names: %v", err) + return failResponse(utils.Fail), nil + } + if list == nil { + list = []dao.SaleGroupNameItem{} + } + return okResponse(list), nil +} diff --git a/services/sale/internal/logic/helper.go b/services/sale/internal/logic/helper.go new file mode 100644 index 0000000..ea224af --- /dev/null +++ b/services/sale/internal/logic/helper.go @@ -0,0 +1,94 @@ +package logic + +import ( + "strconv" + + "lone-services/pkg/modelbase" + "lone-services/pkg/utils" + "lone-services/services/sale/internal/dao" + "lone-services/services/sale/internal/model" + "lone-services/services/sale/validator" +) + +func saleTypeOptions() []dao.SaleTypeOption { + return []dao.SaleTypeOption{ + {Value: dao.SaleTypeStaff, Label: "销售人员"}, + {Value: dao.SaleTypeAgentCorp, Label: "销售商(法人)"}, + {Value: dao.SaleTypeAgentPerson, Label: "销售商(个人)"}, + } +} + +func buildRegion(province, city, district string) dao.RegionNames { + return dao.RegionNames{ + Province: province, + City: city, + District: district, + } +} + +func querySaleNames(req validator.NamesValidator) ([]dao.SaleNameItem, error) { + w := modelbase.Params{ + Eq: map[string]string{"status": strconv.Itoa(int(dao.SaleStatusApproved))}, + Order: "id desc", + Like: map[string]string{}, + } + if req.Type > utils.NumberZero { + w.Eq["type"] = strconv.Itoa(int(req.Type)) + } + if req.Level == utils.NumberOne { + w.Eq["sale_id"] = strconv.Itoa(utils.NumberZero) + } + if req.Name != utils.StringEmpty { + w.Like["name LIKE ?"] = "%" + req.Name + "%" + } + + var items []dao.SaleNameItem + m := model.SaleModel{}.Init() + if err := m.Items(w, &items); err != nil { + return nil, err + } + if items == nil { + items = []dao.SaleNameItem{} + } + maskSaleNameItems(items) + return items, nil +} + +func maskSaleMobile(info *dao.SaleInfo) { + if info == nil { + return + } + info.OriginMobile = info.Mobile + mobile, err := utils.DecryptPhone(info.Mobile) + if err != nil { + return + } + info.Mobile = utils.DecryptPhoneReplace(mobile) +} + +func maskSaleNameItems(items []dao.SaleNameItem) { + for i := range items { + mobile, err := utils.DecryptPhone(items[i].Mobile) + if err != nil { + continue + } + items[i].Mobile = utils.DecryptPhoneReplace(mobile) + } +} + +func validateSaleTypeRules(saleType uint32, account, businessLicense string) string { + switch uint8(saleType) { + case dao.SaleTypeAgentCorp: + if account == utils.StringEmpty { + return "缺少账户信息" + } + if businessLicense == utils.StringEmpty { + return "缺少营业执照" + } + case dao.SaleTypeAgentPerson: + if account == utils.StringEmpty { + return "缺少账户信息" + } + } + return utils.StringEmpty +} diff --git a/services/sale/internal/logic/infoLogic.go b/services/sale/internal/logic/infoLogic.go new file mode 100644 index 0000000..aa46ae5 --- /dev/null +++ b/services/sale/internal/logic/infoLogic.go @@ -0,0 +1,51 @@ +package logic + +import ( + "context" + "strconv" + + "lone-services/pkg/modelbase" + "lone-services/pkg/utils" + "lone-services/pkg/validate" + sale "lone-services/rpc/sale/pb" + "lone-services/services/sale/internal/dao" + "lone-services/services/sale/internal/model" + "lone-services/services/sale/internal/svc" + "lone-services/services/sale/validator" + + "github.com/zeromicro/go-zero/core/logx" +) + +type InfoLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *InfoLogic { + return &InfoLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *InfoLogic) Info(in *sale.InfoReq) (*sale.Response, error) { + var req validator.InfoValidator + if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { + return outResponse(utils.ErrorParams, msg), nil + } + + var info dao.SaleInfo + if err := (model.SaleModel{}.Init().GetOne(modelbase.Params{ + Eq: map[string]string{"id": strconv.FormatInt(req.Id, 10)}, + }, &info)); err != nil { + l.Errorf("sale info: %v", err) + return failResponse(utils.Fail), nil + } + if info.Id < utils.NumberOne { + return failResponse(utils.ErrorNotFund), nil + } + maskSaleMobile(&info) + return okResponse(info), nil +} diff --git a/services/sale/internal/logic/itemsLogic.go b/services/sale/internal/logic/itemsLogic.go new file mode 100644 index 0000000..09b18e0 --- /dev/null +++ b/services/sale/internal/logic/itemsLogic.go @@ -0,0 +1,89 @@ +package logic + +import ( + "context" + "strconv" + + "lone-services/pkg/modelbase" + "lone-services/pkg/utils" + "lone-services/pkg/validate" + sale "lone-services/rpc/sale/pb" + "lone-services/services/sale/internal/dao" + "lone-services/services/sale/internal/model" + "lone-services/services/sale/internal/svc" + "lone-services/services/sale/validator" + + "github.com/zeromicro/go-zero/core/logx" +) + +type ItemsLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewItemsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ItemsLogic { + return &ItemsLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *ItemsLogic) Items(in *sale.ItemsReq) (*sale.Response, error) { + var req validator.ItemsValidator + if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { + return outResponse(utils.ErrorParams, msg), nil + } + + page := int(req.Page) + size := int(req.PageSize) + if page < modelbase.DefaultPage { + page = modelbase.DefaultPage + } + if size < modelbase.DefaultPage { + size = modelbase.DefaultSize + } + + w := modelbase.Params{ + Eq: map[string]string{}, + Page: page, + Size: size, + Order: "id desc", + Like: map[string]string{}, + In: map[string][]string{ + "status": { + strconv.Itoa(int(dao.SaleStatusApproved)), + strconv.Itoa(int(dao.SaleStatusDisabled)), + }, + }, + } + if req.Type > utils.NumberZero { + w.Eq["type"] = strconv.Itoa(int(req.Type)) + } + if req.SaleId > utils.NumberZero { + w.Eq["sale_id"] = strconv.FormatInt(req.SaleId, 10) + } + if req.Status > utils.NumberZero { + delete(w.In, "status") + w.Eq["status"] = strconv.Itoa(int(req.Status)) + } + if req.Name != utils.StringEmpty { + w.Like["name LIKE ?"] = "%" + req.Name + "%" + } + + var list []dao.SaleInfo + result, err := model.SaleModel{}.Init().Page(w, &list) + if err != nil { + l.Errorf("sale items: %v", err) + return failResponse(utils.Fail), nil + } + for i := range list { + maskSaleMobile(&list[i]) + } + + return okResponse(map[string]any{ + "count": result.Count, + "items": list, + }), nil +} diff --git a/services/sale/internal/logic/namesInternalLogic.go b/services/sale/internal/logic/namesInternalLogic.go new file mode 100644 index 0000000..8aab260 --- /dev/null +++ b/services/sale/internal/logic/namesInternalLogic.go @@ -0,0 +1,57 @@ +package logic + +import ( + "context" + + "lone-services/pkg/utils" + "lone-services/pkg/validate" + sale "lone-services/rpc/sale/pb" + "lone-services/services/sale/internal/dao" + "lone-services/services/sale/internal/svc" + "lone-services/services/sale/validator" + + "github.com/zeromicro/go-zero/core/logx" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type NamesInternalLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewNamesInternalLogic(ctx context.Context, svcCtx *svc.ServiceContext) *NamesInternalLogic { + return &NamesInternalLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *NamesInternalLogic) NamesInternal(in *sale.NamesReq) (*sale.NamesData, error) { + var req validator.NamesValidator + if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { + return nil, status.Error(codes.InvalidArgument, msg) + } + + items, err := querySaleNames(req) + if err != nil { + l.Errorf("sale NamesInternal: %v", err) + return nil, status.Error(codes.Internal, utils.Fail.Msg) + } + + return &sale.NamesData{Items: toSaleNameItems(items)}, nil +} + +func toSaleNameItems(items []dao.SaleNameItem) []*sale.NameItem { + result := make([]*sale.NameItem, 0, len(items)) + for _, item := range items { + result = append(result, &sale.NameItem{ + Id: item.Id, + Mobile: item.Mobile, + Name: item.Name, + }) + } + return result +} diff --git a/services/sale/internal/logic/namesLogic.go b/services/sale/internal/logic/namesLogic.go new file mode 100644 index 0000000..304f675 --- /dev/null +++ b/services/sale/internal/logic/namesLogic.go @@ -0,0 +1,41 @@ +package logic + +import ( + "context" + + "lone-services/pkg/utils" + "lone-services/pkg/validate" + sale "lone-services/rpc/sale/pb" + "lone-services/services/sale/internal/svc" + "lone-services/services/sale/validator" + + "github.com/zeromicro/go-zero/core/logx" +) + +type NamesLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewNamesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *NamesLogic { + return &NamesLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *NamesLogic) Names(in *sale.NamesReq) (*sale.Response, error) { + var req validator.NamesValidator + if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { + return outResponse(utils.ErrorParams, msg), nil + } + + items, err := querySaleNames(req) + if err != nil { + l.Errorf("sale names: %v", err) + return failResponse(utils.Fail), nil + } + return okResponse(items), nil +} diff --git a/services/sale/internal/logic/response.go b/services/sale/internal/logic/response.go new file mode 100644 index 0000000..3d75285 --- /dev/null +++ b/services/sale/internal/logic/response.go @@ -0,0 +1,39 @@ +package logic + +import ( + "lone-services/pkg/utils" + sale "lone-services/rpc/sale/pb" + + jsoniter "github.com/json-iterator/go" +) + +func okResponse(data any) *sale.Response { + buf, _ := jsoniter.Marshal(data) + return &sale.Response{ + Code: utils.Ok.Code, + Msg: utils.Ok.Msg, + Data: string(buf), + } +} + +func okStringResponse(data string) *sale.Response { + return &sale.Response{ + Code: utils.Ok.Code, + Msg: utils.Ok.Msg, + Data: data, + } +} + +func failResponse(status utils.Status) *sale.Response { + return &sale.Response{ + Code: status.Code, + Msg: status.Msg, + } +} + +func outResponse(status utils.Status, msg string) *sale.Response { + return &sale.Response{ + Code: status.Code, + Msg: msg, + } +} diff --git a/services/sale/internal/logic/statusLogic.go b/services/sale/internal/logic/statusLogic.go new file mode 100644 index 0000000..50158c1 --- /dev/null +++ b/services/sale/internal/logic/statusLogic.go @@ -0,0 +1,74 @@ +package logic + +import ( + "context" + "strconv" + + "lone-services/pkg/modelbase" + "lone-services/pkg/utils" + "lone-services/pkg/validate" + sale "lone-services/rpc/sale/pb" + "lone-services/services/sale/internal/dao" + "lone-services/services/sale/internal/model" + "lone-services/services/sale/internal/svc" + "lone-services/services/sale/validator" + + "github.com/zeromicro/go-zero/core/logx" +) + +type StatusLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *StatusLogic { + return &StatusLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *StatusLogic) Status(in *sale.StatusReq) (*sale.Response, error) { + var req validator.StatusValidator + if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { + return outResponse(utils.ErrorParams, msg), nil + } + + adminInfo := utils.GetUserFromCtx(l.ctx) + if adminInfo.ID < utils.NumberOne { + return failResponse(utils.ErrorNoLoginInfo), nil + } + + w := modelbase.Params{ + Eq: map[string]string{"id": strconv.FormatInt(req.Id, 10)}, + In: map[string][]string{ + "status": { + strconv.Itoa(int(dao.SaleStatusApproved)), + strconv.Itoa(int(dao.SaleStatusDisabled)), + }, + }, + } + var info dao.SaleStatusUpdate + m := model.SaleModel{}.Init() + if err := m.GetOne(w, &info); err != nil { + l.Errorf("sale status get: %v", err) + return failResponse(utils.Fail), nil + } + if info.Id < utils.NumberOne { + return failResponse(utils.ErrorNotFund), nil + } + + info.Status = uint8(req.Status) + info.Reason = req.Reason + info.AdminId = adminInfo.ID + info.AdminName = adminInfo.Name + + if _, err := m.Edit(modelbase.Params{Eq: map[string]string{"id": strconv.FormatInt(req.Id, 10)}}, &info); err != nil { + l.Errorf("sale status edit: %v", err) + return failResponse(utils.Fail), nil + } + + return okStringResponse(utils.StringEmpty), nil +} diff --git a/services/sale/internal/logic/typesLogic.go b/services/sale/internal/logic/typesLogic.go new file mode 100644 index 0000000..c8d3f85 --- /dev/null +++ b/services/sale/internal/logic/typesLogic.go @@ -0,0 +1,28 @@ +package logic + +import ( + "context" + + sale "lone-services/rpc/sale/pb" + "lone-services/services/sale/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type TypesLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewTypesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *TypesLogic { + return &TypesLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *TypesLogic) Types(_ *sale.GroupEmptyReq) (*sale.Response, error) { + return okResponse(saleTypeOptions()), nil +} diff --git a/services/sale/internal/model/sale_group_model.go b/services/sale/internal/model/sale_group_model.go new file mode 100644 index 0000000..f7a5399 --- /dev/null +++ b/services/sale/internal/model/sale_group_model.go @@ -0,0 +1,23 @@ +package model + +import ( + "lone-services/pkg/modelbase" + "lone-services/services/sale/internal/dao" +) + +type SaleGroupModel struct { + modelbase.Base +} + +func (m SaleGroupModel) TableName() string { + return modelbase.Prefix() + "group" +} + +func (m SaleGroupModel) Init() SaleGroupModel { + m.Table = m.TableName() + return m +} + +func (m SaleGroupModel) Create(data *dao.SaleGroupCreate) error { + return m.Base.Create(data) +} diff --git a/services/sale/internal/model/sale_model.go b/services/sale/internal/model/sale_model.go new file mode 100644 index 0000000..e33dd69 --- /dev/null +++ b/services/sale/internal/model/sale_model.go @@ -0,0 +1,23 @@ +package model + +import ( + "lone-services/pkg/modelbase" + "lone-services/services/sale/internal/dao" +) + +type SaleModel struct { + modelbase.Base +} + +func (m SaleModel) TableName() string { + return modelbase.Prefix() + "sales" +} + +func (m SaleModel) Init() SaleModel { + m.Table = m.TableName() + return m +} + +func (m SaleModel) Create(data *dao.SaleCreate) error { + return m.Base.Create(data) +} diff --git a/services/sale/internal/server/saleServer.go b/services/sale/internal/server/saleServer.go new file mode 100644 index 0000000..2e1b92d --- /dev/null +++ b/services/sale/internal/server/saleServer.go @@ -0,0 +1,81 @@ +// Code generated by goctl. DO NOT EDIT. +// goctl 1.10.1 +// Source: sale.proto + +package server + +import ( + "context" + + "lone-services/rpc/sale/pb" + "lone-services/services/sale/internal/logic" + "lone-services/services/sale/internal/svc" +) + +type SaleServer struct { + svcCtx *svc.ServiceContext + sale.UnimplementedSaleServer +} + +func NewSaleServer(svcCtx *svc.ServiceContext) *SaleServer { + return &SaleServer{ + svcCtx: svcCtx, + } +} + +// 销售分组 +func (s *SaleServer) GroupItems(ctx context.Context, in *sale.GroupItemsReq) (*sale.Response, error) { + l := logic.NewGroupItemsLogic(ctx, s.svcCtx) + return l.GroupItems(in) +} + +func (s *SaleServer) GroupCreate(ctx context.Context, in *sale.GroupCreateReq) (*sale.Response, error) { + l := logic.NewGroupCreateLogic(ctx, s.svcCtx) + return l.GroupCreate(in) +} + +func (s *SaleServer) GroupNames(ctx context.Context, in *sale.GroupEmptyReq) (*sale.Response, error) { + l := logic.NewGroupNamesLogic(ctx, s.svcCtx) + return l.GroupNames(in) +} + +// 销售管理 +func (s *SaleServer) Types(ctx context.Context, in *sale.GroupEmptyReq) (*sale.Response, error) { + l := logic.NewTypesLogic(ctx, s.svcCtx) + return l.Types(in) +} + +func (s *SaleServer) Names(ctx context.Context, in *sale.NamesReq) (*sale.Response, error) { + l := logic.NewNamesLogic(ctx, s.svcCtx) + return l.Names(in) +} + +func (s *SaleServer) NamesInternal(ctx context.Context, in *sale.NamesReq) (*sale.NamesData, error) { + l := logic.NewNamesInternalLogic(ctx, s.svcCtx) + return l.NamesInternal(in) +} + +func (s *SaleServer) Create(ctx context.Context, in *sale.CreateReq) (*sale.Response, error) { + l := logic.NewCreateLogic(ctx, s.svcCtx) + return l.Create(in) +} + +func (s *SaleServer) Edit(ctx context.Context, in *sale.EditReq) (*sale.Response, error) { + l := logic.NewEditLogic(ctx, s.svcCtx) + return l.Edit(in) +} + +func (s *SaleServer) Info(ctx context.Context, in *sale.InfoReq) (*sale.Response, error) { + l := logic.NewInfoLogic(ctx, s.svcCtx) + return l.Info(in) +} + +func (s *SaleServer) Items(ctx context.Context, in *sale.ItemsReq) (*sale.Response, error) { + l := logic.NewItemsLogic(ctx, s.svcCtx) + return l.Items(in) +} + +func (s *SaleServer) Status(ctx context.Context, in *sale.StatusReq) (*sale.Response, error) { + l := logic.NewStatusLogic(ctx, s.svcCtx) + return l.Status(in) +} diff --git a/services/sale/internal/svc/serviceContext.go b/services/sale/internal/svc/serviceContext.go new file mode 100644 index 0000000..5985725 --- /dev/null +++ b/services/sale/internal/svc/serviceContext.go @@ -0,0 +1,22 @@ +package svc + +import ( + "lone-services/pkg/utils" + "lone-services/services/sale/internal/config" + + "gorm.io/gorm" +) + +type ServiceContext struct { + Config config.Config + DB *gorm.DB + Prefix string +} + +func NewServiceContext(c config.Config, db *gorm.DB) *ServiceContext { + return &ServiceContext{ + Config: c, + DB: db, + Prefix: utils.GetConfigString("mysql.prefix"), + } +} diff --git a/services/sale/run.toml b/services/sale/run.toml new file mode 100644 index 0000000..de652ef --- /dev/null +++ b/services/sale/run.toml @@ -0,0 +1,55 @@ +[base] + login_out_time=43200 #api接口超时时间分 + login_refresh_out_time=83200 + name = "sale-service" + listenOn = "0.0.0.0:10300" + mode = "dev" +[log] + path = "logs" + serviceName = "sale-service" + mode = "file" + encoding = "plain" + level = "info" + keepDays = 7 + maxSize = 50 + maxBackups = 5 + compress = false + +[oss] + accessKeyId = "LTAI5t7U8KvxSiPE5auwQUuu" + accessKeySecret = "xjfgbQQRpL4TcIspNuClg6bYADa3pk" + roleArn = "acs:ram::1663896742753915:role/oss-upload" + roleSessionName = "oss-upload" + region = "oss-cn-hangzhou" + bucketName = "lone-images" + endpoint = "https://oss-accelerate.aliyuncs.com" + host = "https://images.ailuowan.com" + dir = "upload/" + expireSeconds = 3600 + +[mysql] + host = '39.106.171.204' + port = 33066 + user = 'root' + password = 'MOLXRZNOU4Y4' + database = 'dms-sale' + charset = 'utf8mb4' + prefix = '' + debug = true +[mysql_read] + host = '39.106.171.204' + port = 33066 + user = 'root' + password = 'MOLXRZNOU4Y4' + database = 'dms-sale' + charset = 'utf8mb4' + prefix = '' + +[redis] + host = '39.106.171.204' + password = 'lLMLcuPpzSj' + port = 6379 + db = 0 + +[encrypt] + data_key = "u2t9T3luZtoRfhBstkFN6TiIMW38BA8a" \ No newline at end of file diff --git a/services/sale/sale.go b/services/sale/sale.go new file mode 100644 index 0000000..60e4165 --- /dev/null +++ b/services/sale/sale.go @@ -0,0 +1,150 @@ +package main + +import ( + "flag" + "lone-services/pkg/discovery" + "lone-services/pkg/modelbase" + "lone-services/pkg/mysql" + "lone-services/pkg/redis" + "lone-services/pkg/utils" + "lone-services/pkg/validate" + sale "lone-services/rpc/sale/pb" + "lone-services/services/sale/internal/config" + "lone-services/services/sale/internal/server" + "lone-services/services/sale/internal/svc" + "net" + "os" + "strconv" + + "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/core/service" + "github.com/zeromicro/go-zero/zrpc" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" +) + +var configFile = flag.String("f", "etc/sale.yaml", "the config file") + +func main() { + flag.Parse() + var c config.Config + conf.MustLoad(*configFile, &c) + + nacosParam := utils.NacosConfig{ + Hosts: c.Nacos.Hosts, + NamespaceId: c.Nacos.NamespaceId, + Group: c.Nacos.Group, + ConfigID: c.Nacos.ConfigID, + } + utils.InitConfig(nacosParam) + + logConf := logx.LogConf{ + ServiceName: utils.GetConfigString("log.serviceName"), + Mode: utils.GetConfigString("log.mode"), + Encoding: utils.GetConfigString("log.encoding"), + Level: utils.GetConfigString("log.level"), + Path: utils.GetConfigString("log.path"), + KeepDays: utils.GetConfigInt("log.keepDays"), + MaxSize: utils.GetConfigInt("log.maxSize"), + MaxBackups: utils.GetConfigInt("log.maxBackups"), + Compress: utils.GetConfigBool("log.compress"), + } + logx.SetUp(logConf) + logx.AddWriter(logx.NewWriter(os.Stdout)) + + listenOn := utils.GetConfigString("base.listenOn") + mode := utils.GetConfigString("base.mode") + serviceName := utils.GetConfigString("base.name") + + if err := discovery.Init(discovery.Config{ + Hosts: c.Nacos.Hosts, + NamespaceId: c.Nacos.NamespaceId, + Group: c.Nacos.Group, + }); err != nil { + logx.Errorf("nacos init: %v", err) + os.Exit(1) + } + + port, err := listenPort(listenOn) + if err != nil { + logx.Errorf("parse ListenOn: %v", err) + os.Exit(1) + } + + if err := discovery.Register(discovery.Instance{ + ServiceName: serviceName, + IP: c.Nacos.RegisterIP, + Port: port, + Group: c.Nacos.Group, + }); err != nil { + logx.Errorf("nacos register: %v", err) + os.Exit(1) + } + logx.Infof("服务注册成功: %s:%d", c.Nacos.RegisterIP, port) + + defer func() { + if err := discovery.Deregister(); err != nil { + logx.Errorf("nacos deregister: %v", err) + } + }() + + db, err := mysql.New(mysql.Config{ + Host: utils.GetConfigString("mysql.host"), + Port: utils.GetConfigInt("mysql.port"), + User: utils.GetConfigString("mysql.user"), + Password: utils.GetConfigString("mysql.password"), + Database: utils.GetConfigString("mysql.database"), + Charset: utils.GetConfigString("mysql.charset"), + Prefix: utils.GetConfigString("mysql.prefix"), + ReadHost: utils.GetConfigString("mysql_read.host"), + ReadPort: utils.GetConfigInt("mysql_read.port"), + ReadUser: utils.GetConfigString("mysql_read.user"), + ReadPassword: utils.GetConfigString("mysql_read.password"), + ReadDatabase: utils.GetConfigString("mysql_read.database"), + }) + if err != nil { + logx.Errorf("mysql init: %v", err) + os.Exit(1) + } + + if err := redis.Init(redis.Config{ + Host: utils.GetConfigString("redis.host"), + Port: utils.GetConfigInt("redis.port"), + Password: utils.GetConfigString("redis.password"), + DB: utils.GetConfigInt("redis.db"), + }); err != nil { + logx.Errorf("redis init: %v", err) + os.Exit(1) + } + + debug := utils.GetConfigBool("mysql.debug") + modelbase.Init(db, modelbase.Config{Prefix: utils.GetConfigString("mysql.prefix"), Debug: debug}) + + rpcConf := zrpc.RpcServerConf{ + ListenOn: listenOn, + } + rpcConf.Mode = mode + ctx := svc.NewServiceContext(c, db) + + s := zrpc.MustNewServer(rpcConf, func(grpcServer *grpc.Server) { + sale.RegisterSaleServer(grpcServer, server.NewSaleServer(ctx)) + if mode == service.DevMode || mode == service.TestMode { + reflection.Register(grpcServer) + } + }) + defer s.Stop() + + s.AddUnaryInterceptors(validate.UnaryServerInterceptor(validate.MustNew())) + + logx.Infof("Starting rpc server at %s...", listenOn) + s.Start() +} + +func listenPort(listenOn string) (uint64, error) { + _, portStr, err := net.SplitHostPort(listenOn) + if err != nil { + return utils.NumberZero, err + } + return strconv.ParseUint(portStr, utils.NumberTen, utils.NumberSixtyFourth) +} diff --git a/services/sale/saleClient/sale.go b/services/sale/saleClient/sale.go new file mode 100644 index 0000000..aa77181 --- /dev/null +++ b/services/sale/saleClient/sale.go @@ -0,0 +1,112 @@ +// Code generated by goctl. DO NOT EDIT. +// goctl 1.10.1 +// Source: sale.proto + +package saleClient + +import ( + "context" + + "lone-services/rpc/sale/pb" + + "github.com/zeromicro/go-zero/zrpc" + "google.golang.org/grpc" +) + +type ( + CreateReq = sale.CreateReq + EditReq = sale.EditReq + GroupCreateReq = sale.GroupCreateReq + GroupEmptyReq = sale.GroupEmptyReq + GroupItemsReq = sale.GroupItemsReq + InfoReq = sale.InfoReq + ItemsReq = sale.ItemsReq + NameItem = sale.NameItem + NamesData = sale.NamesData + NamesReq = sale.NamesReq + Response = sale.Response + StatusReq = sale.StatusReq + + Sale interface { + // 销售分组 + GroupItems(ctx context.Context, in *GroupItemsReq, opts ...grpc.CallOption) (*Response, error) + GroupCreate(ctx context.Context, in *GroupCreateReq, opts ...grpc.CallOption) (*Response, error) + GroupNames(ctx context.Context, in *GroupEmptyReq, opts ...grpc.CallOption) (*Response, error) + // 销售管理 + Types(ctx context.Context, in *GroupEmptyReq, opts ...grpc.CallOption) (*Response, error) + Names(ctx context.Context, in *NamesReq, opts ...grpc.CallOption) (*Response, error) + NamesInternal(ctx context.Context, in *NamesReq, opts ...grpc.CallOption) (*NamesData, error) + Create(ctx context.Context, in *CreateReq, opts ...grpc.CallOption) (*Response, error) + Edit(ctx context.Context, in *EditReq, opts ...grpc.CallOption) (*Response, error) + Info(ctx context.Context, in *InfoReq, opts ...grpc.CallOption) (*Response, error) + Items(ctx context.Context, in *ItemsReq, opts ...grpc.CallOption) (*Response, error) + Status(ctx context.Context, in *StatusReq, opts ...grpc.CallOption) (*Response, error) + } + + defaultSale struct { + cli zrpc.Client + } +) + +func NewSale(cli zrpc.Client) Sale { + return &defaultSale{ + cli: cli, + } +} + +// 销售分组 +func (m *defaultSale) GroupItems(ctx context.Context, in *GroupItemsReq, opts ...grpc.CallOption) (*Response, error) { + client := sale.NewSaleClient(m.cli.Conn()) + return client.GroupItems(ctx, in, opts...) +} + +func (m *defaultSale) GroupCreate(ctx context.Context, in *GroupCreateReq, opts ...grpc.CallOption) (*Response, error) { + client := sale.NewSaleClient(m.cli.Conn()) + return client.GroupCreate(ctx, in, opts...) +} + +func (m *defaultSale) GroupNames(ctx context.Context, in *GroupEmptyReq, opts ...grpc.CallOption) (*Response, error) { + client := sale.NewSaleClient(m.cli.Conn()) + return client.GroupNames(ctx, in, opts...) +} + +// 销售管理 +func (m *defaultSale) Types(ctx context.Context, in *GroupEmptyReq, opts ...grpc.CallOption) (*Response, error) { + client := sale.NewSaleClient(m.cli.Conn()) + return client.Types(ctx, in, opts...) +} + +func (m *defaultSale) Names(ctx context.Context, in *NamesReq, opts ...grpc.CallOption) (*Response, error) { + client := sale.NewSaleClient(m.cli.Conn()) + return client.Names(ctx, in, opts...) +} + +func (m *defaultSale) NamesInternal(ctx context.Context, in *NamesReq, opts ...grpc.CallOption) (*NamesData, error) { + client := sale.NewSaleClient(m.cli.Conn()) + return client.NamesInternal(ctx, in, opts...) +} + +func (m *defaultSale) Create(ctx context.Context, in *CreateReq, opts ...grpc.CallOption) (*Response, error) { + client := sale.NewSaleClient(m.cli.Conn()) + return client.Create(ctx, in, opts...) +} + +func (m *defaultSale) Edit(ctx context.Context, in *EditReq, opts ...grpc.CallOption) (*Response, error) { + client := sale.NewSaleClient(m.cli.Conn()) + return client.Edit(ctx, in, opts...) +} + +func (m *defaultSale) Info(ctx context.Context, in *InfoReq, opts ...grpc.CallOption) (*Response, error) { + client := sale.NewSaleClient(m.cli.Conn()) + return client.Info(ctx, in, opts...) +} + +func (m *defaultSale) Items(ctx context.Context, in *ItemsReq, opts ...grpc.CallOption) (*Response, error) { + client := sale.NewSaleClient(m.cli.Conn()) + return client.Items(ctx, in, opts...) +} + +func (m *defaultSale) Status(ctx context.Context, in *StatusReq, opts ...grpc.CallOption) (*Response, error) { + client := sale.NewSaleClient(m.cli.Conn()) + return client.Status(ctx, in, opts...) +} diff --git a/services/sale/validator/validator.go b/services/sale/validator/validator.go new file mode 100644 index 0000000..436185c --- /dev/null +++ b/services/sale/validator/validator.go @@ -0,0 +1,200 @@ +package validator + +import "lone-services/pkg/validate" + +type GroupItemsValidator struct { + Page uint32 `validate:"omitempty,min=1"` + PageSize uint32 `validate:"omitempty,min=1,max=100"` + Name string `validate:"omitempty,max=255"` +} + +func (p GroupItemsValidator) GetMessage() validate.ValidatorMessages { + return validate.ValidatorMessages{ + "Page.min": "页码最小为1", + "PageSize.min": "每页数量最小为1", + "PageSize.max": "每页数量最大为100", + "Name.max": "名称长度不能超过255", + } +} + +type GroupCreateValidator struct { + Name string `validate:"required,max=255"` +} + +func (p GroupCreateValidator) GetMessage() validate.ValidatorMessages { + return validate.ValidatorMessages{ + "Name.required": "分组名称不能为空", + "Name.max": "分组名称长度不能超过255", + } +} + +type NamesValidator struct { + Type uint32 `validate:"omitempty,oneof=1 2 3"` + Name string `validate:"omitempty,max=255"` + Level uint32 `validate:"omitempty,oneof=0 1"` +} + +func (p NamesValidator) GetMessage() validate.ValidatorMessages { + return validate.ValidatorMessages{ + "Type.oneof": "类型不对", + "Name.max": "名称长度不能超过255", + "Level.oneof": "级别不对", + } +} + +type CreateValidator struct { + Mobile string `validate:"required,max=20"` + Name string `validate:"required,max=256"` + IdCardFront string `validate:"required,max=255"` + IdCardBack string `validate:"required,max=255"` + BusinessLicense string `validate:"omitempty,max=255"` + Password string `validate:"required,min=6"` + Account string `validate:"omitempty,max=255"` + Sex uint32 `validate:"omitempty,oneof=1 2 3"` + GroupId int64 `validate:"required,gt=0"` + BirthDate string `validate:"omitempty,max=12"` + SaleId int64 `validate:"omitempty,gte=0"` + Type uint32 `validate:"required,oneof=1 2 3"` + TerritoryId int64 `validate:"required,gt=0"` + TerritoryName string `validate:"required,max=255"` + ProvinceId int64 `validate:"required,gt=0"` + CityId int64 `validate:"required,gt=0"` + DistrictId int64 `validate:"required,gt=0"` + RegionProvince string `validate:"required,max=64"` + RegionCity string `validate:"required,max=64"` + RegionDistrict string `validate:"required,max=64"` + Address string `validate:"required,max=255"` +} + +func (p CreateValidator) GetMessage() validate.ValidatorMessages { + return validate.ValidatorMessages{ + "Mobile.required": "手机号不能为空", + "Name.required": "姓名不能为空", + "IdCardFront.required": "身份证正面不能为空", + "IdCardFront.max": "身份证正面地址过长", + "IdCardBack.required": "身份证反面不能为空", + "IdCardBack.max": "身份证反面地址过长", + "BusinessLicense.max": "营业执照地址过长", + "Password.required": "密码不能为空", + "Password.min": "密码长度不能小于6位", + "GroupId.required": "请选择销售分组", + "GroupId.gt": "请选择销售分组", + "Type.required": "请选择类型", + "Type.oneof": "类型不对", + "TerritoryId.required": "请选择地域", + "TerritoryId.gt": "请选择地域", + "TerritoryName.required": "地域名称不能为空", + "ProvinceId.required": "请选择省份", + "ProvinceId.gt": "请选择省份", + "CityId.required": "请选择城市", + "CityId.gt": "请选择城市", + "DistrictId.required": "请选择区县", + "DistrictId.gt": "请选择区县", + "RegionProvince.required": "地区省份不能为空", + "RegionCity.required": "地区城市不能为空", + "RegionDistrict.required": "地区区县不能为空", + "Address.required": "详细地址不能为空", + } +} + +type EditValidator struct { + Id int64 `validate:"required,gt=0"` + Mobile string `validate:"required,max=20"` + Name string `validate:"required,max=256"` + IdCardFront string `validate:"required,max=255"` + IdCardBack string `validate:"required,max=255"` + BusinessLicense string `validate:"omitempty,max=255"` + Account string `validate:"omitempty,max=255"` + Sex uint32 `validate:"omitempty,oneof=1 2 3"` + GroupId int64 `validate:"required,gt=0"` + BirthDate string `validate:"omitempty,max=12"` + SaleId int64 `validate:"omitempty,gte=0"` + Type uint32 `validate:"required,oneof=1 2 3"` + TerritoryId int64 `validate:"required,gt=0"` + TerritoryName string `validate:"required,max=255"` + ProvinceId int64 `validate:"required,gt=0"` + CityId int64 `validate:"required,gt=0"` + DistrictId int64 `validate:"required,gt=0"` + RegionProvince string `validate:"required,max=64"` + RegionCity string `validate:"required,max=64"` + RegionDistrict string `validate:"required,max=64"` + Address string `validate:"required,max=255"` +} + +func (p EditValidator) GetMessage() validate.ValidatorMessages { + return validate.ValidatorMessages{ + "Id.required": "ID不能为空", + "Id.gt": "ID必须大于0", + "Mobile.required": "手机号不能为空", + "Name.required": "姓名不能为空", + "IdCardFront.required": "身份证正面不能为空", + "IdCardFront.max": "身份证正面地址过长", + "IdCardBack.required": "身份证反面不能为空", + "IdCardBack.max": "身份证反面地址过长", + "BusinessLicense.max": "营业执照地址过长", + "GroupId.required": "请选择销售分组", + "GroupId.gt": "请选择销售分组", + "Type.required": "请选择类型", + "Type.oneof": "类型不对", + "TerritoryId.required": "请选择地域", + "TerritoryId.gt": "请选择地域", + "TerritoryName.required": "地域名称不能为空", + "ProvinceId.required": "请选择省份", + "ProvinceId.gt": "请选择省份", + "CityId.required": "请选择城市", + "CityId.gt": "请选择城市", + "DistrictId.required": "请选择区县", + "DistrictId.gt": "请选择区县", + "RegionProvince.required": "地区省份不能为空", + "RegionCity.required": "地区城市不能为空", + "RegionDistrict.required": "地区区县不能为空", + "Address.required": "详细地址不能为空", + } +} + +type InfoValidator struct { + Id int64 `validate:"required,gt=0"` +} + +func (p InfoValidator) GetMessage() validate.ValidatorMessages { + return validate.ValidatorMessages{ + "Id.required": "ID不能为空", + "Id.gt": "ID必须大于0", + } +} + +type ItemsValidator struct { + Name string `validate:"omitempty,max=256"` + Page uint32 `validate:"omitempty,min=1"` + PageSize uint32 `validate:"omitempty,min=1,max=100"` + SaleId int64 `validate:"omitempty,gte=0"` + Type uint32 `validate:"omitempty,oneof=1 2 3"` + Status uint32 `validate:"omitempty,oneof=1 2 3 9"` +} + +func (p ItemsValidator) GetMessage() validate.ValidatorMessages { + return validate.ValidatorMessages{ + "Page.min": "页码最小为1", + "PageSize.min": "每页数量最小为1", + "PageSize.max": "每页数量最大为100", + "Type.oneof": "类型不对", + "Status.oneof": "状态不对", + } +} + +type StatusValidator struct { + Id int64 `validate:"required,gt=0"` + Status uint32 `validate:"required,oneof=1 2 3"` + Reason string `validate:"required_if=Status 2 required_if=Status 3,max=255"` +} + +func (p StatusValidator) GetMessage() validate.ValidatorMessages { + return validate.ValidatorMessages{ + "Id.required": "ID不能为空", + "Id.gt": "ID必须大于0", + "Status.required": "状态不能为空", + "Status.oneof": "状态不对", + "Reason.required_if": "未通过或禁用状态,理由不能为空", + "Reason.max": "理由长度不能超过255", + } +} diff --git a/services/user/internal/dao/user.go b/services/user/internal/dao/user.go index e4c7350..9c3192e 100644 --- a/services/user/internal/dao/user.go +++ b/services/user/internal/dao/user.go @@ -100,6 +100,7 @@ type UserListItem struct { Nickname string `json:"nickname"` HeadPortrait string `json:"head_portrait"` Mobile string `json:"mobile"` + OriginMobile string `json:"origin_mobile"` OnTrialNum int `json:"on_trial_num"` Gender int `json:"gender"` Birthday string `json:"birthday"` diff --git a/services/user/internal/logic/registerByUserLogic.go b/services/user/internal/logic/registerByUserLogic.go index e21a37f..4adf11b 100644 --- a/services/user/internal/logic/registerByUserLogic.go +++ b/services/user/internal/logic/registerByUserLogic.go @@ -83,7 +83,7 @@ func (l *RegisterByUserLogic) RegisterByUser(in *user.RegisterByUserReq) (*user. } if v.Type == utils.NumberOne { - encryptMobile, cErr := utils.Crypto{}.AESEncryptECB(v.Account) + encryptMobile, cErr := utils.EncryptPhone(v.Account) if cErr != nil { l.Errorf("registerByUser encrypt mobile: %v", cErr) return failResponse(utils.ErrorEncryptAesError), nil diff --git a/services/user/internal/logic/registerLogic.go b/services/user/internal/logic/registerLogic.go index 7088763..8598bae 100644 --- a/services/user/internal/logic/registerLogic.go +++ b/services/user/internal/logic/registerLogic.go @@ -51,7 +51,7 @@ func (l *RegisterLogic) Register(in *user.RegisterReq) (*user.Response, error) { return failResponse(utils.ErrorExist), nil } - encryptMobile, cErr := utils.Crypto{}.AESEncryptECB(v.Mobile) + encryptMobile, cErr := utils.EncryptPhone(v.Mobile) if cErr != nil { l.Errorf("register encrypt mobile: %v", cErr) return failResponse(utils.ErrorEncryptAesError), nil diff --git a/services/user/internal/logic/response.go b/services/user/internal/logic/response.go index 26be655..12e7aea 100644 --- a/services/user/internal/logic/response.go +++ b/services/user/internal/logic/response.go @@ -39,7 +39,7 @@ func decryptMobile(mobile string) string { if mobile == utils.StringEmpty { return utils.StringEmpty } - plain, err := utils.Crypto{}.AESDecryptECB(mobile) + plain, err := utils.DecryptPhone(mobile) if err != nil { return utils.StringEmpty } diff --git a/services/user/internal/logic/userItemsLogic.go b/services/user/internal/logic/userItemsLogic.go index 3be1045..c430cec 100644 --- a/services/user/internal/logic/userItemsLogic.go +++ b/services/user/internal/logic/userItemsLogic.go @@ -49,23 +49,22 @@ func (l *UserItemsLogic) UserItems(in *user.UserItemsReq) (*user.Response, error size = modelbase.DefaultSize } - where := map[string]string{} - if v.Mobile != utils.StringEmpty { - mobile, cErr := utils.Crypto{}.AESEncryptECB(v.Mobile) - if cErr != nil { - l.Errorf("user items encrypt mobile: %v", cErr) - return failResponse(utils.ErrorEncryptAesError), nil - } - where["mobile"] = mobile - } - - var list []dao.UserListRow - result, err := model.UserModel{}.Init().Page(modelbase.Params{ - Eq: where, + params := modelbase.Params{ Order: "id DESC", Page: page, Size: size, - }, &list) + } + if v.Mobile != utils.StringEmpty { + phone := utils.GetSearchPhone(v.Mobile) + if len(phone) > utils.NumberZero { + params.Like = map[string]string{ + "mobile LIKE ? ": "%%" + phone + "%%", + } + } + } + + var list []dao.UserListRow + result, err := model.UserModel{}.Init().Page(params, &list) if err != nil { l.Errorf("user items: %v", err) return failResponse(utils.Fail), nil @@ -74,12 +73,17 @@ func (l *UserItemsLogic) UserItems(in *user.UserItemsReq) (*user.Response, error items := make([]dao.UserListItem, 0, len(list)) for _, row := range list { headPortrait, _ := utils.BuildImageURL(row.Avatar).(string) + mobile := row.Mobile + if plain, dErr := utils.DecryptPhone(row.Mobile); dErr == nil { + mobile = utils.DecryptPhoneReplace(plain) + } items = append(items, dao.UserListItem{ Id: row.Id, Username: row.Username, Nickname: row.Nickname, HeadPortrait: headPortrait, - Mobile: utils.DecryptMobile(row.Mobile), + Mobile: mobile, + OriginMobile: row.Mobile, OnTrialNum: row.OnTrialNum, Gender: row.Gender, Birthday: row.Birthday,