Compare commits

..

12 Commits

Author SHA1 Message Date
VLADIMIR 0ed38b7cc0 add text waste route
continuous-integration/drone/push Build is failing
2024-11-28 06:43:05 +07:00
VLADIMIR 26ca649e8e add create waste route
continuous-integration/drone/push Build is passing
2024-11-25 16:38:03 +07:00
VLADIMIR 675c2884b7 add create categories route
continuous-integration/drone/push Build is passing
2024-11-25 13:36:14 +07:00
VLADIMIR 130a3236e0 add add user to budget route
continuous-integration/drone/push Build is passing
2024-11-24 22:24:44 +07:00
VLADIMIR 95fe8b530e add get budgets method
continuous-integration/drone/push Build is passing
2024-11-24 16:53:52 +07:00
VLADIMIR bf85f31056 add create budget route
continuous-integration/drone/push Build is passing
2024-11-24 16:02:13 +07:00
VLADIMIR 866009cf09 add login
continuous-integration/drone/push Build is passing
2024-11-21 16:02:36 +07:00
VLADIMIR f2011b953c remane vars
continuous-integration/drone/push Build is passing
2024-11-21 15:11:21 +07:00
VLADIMIR 66df21c6c9 update api
continuous-integration/drone/push Build is failing
2024-11-21 02:10:29 +07:00
VLADIMIR a8b6e9ab9b update db
continuous-integration/drone/push Build is passing
2024-11-21 01:05:03 +07:00
VLADIMIR 2078e008f3 update db
continuous-integration/drone/push Build is passing
2024-11-21 01:02:15 +07:00
VLADIMIR f4523de5a4 fix db
continuous-integration/drone/push Build is passing
2024-11-21 00:47:44 +07:00
24 changed files with 4881 additions and 465 deletions
+2 -1
View File
@@ -7,7 +7,8 @@
"mode": "debug",
"program": "${workspaceFolder}/cmd/smm_core",
"env": {
"DATABASE_URL": "user=crab password=crab dbname=smm-core host=localhost port=5432 sslmode=disable"
"DATABASE_URL": "user=crab password=crab dbname=smm-core host=localhost port=5432 sslmode=disable",
"AUTHORIZATION": "Y3JhYjpjcmFi"
}
},
]
+22
View File
@@ -0,0 +1,22 @@
{
"sqltools.connections": [
{
"previewLimit": 50,
"server": "localhost",
"port": 5432,
"driver": "PostgreSQL",
"name": "smm",
"database": "smm-core",
"username": "crab",
"password": "crab"
}
],
"cSpell.words": [
"рублей",
"caser",
"dbpool",
"jackc",
"pgconn",
"pgxpool"
]
}
+197 -20
View File
@@ -10,22 +10,71 @@ option go_package = "pkg/proto";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {};
service SmmCore {
// ping
rpc Ping(PingReq) returns (PingRsp) {
option (google.api.http) = {
get: "/ping"
};
}
// users
rpc AddUser(CreateUserReq) returns (User) {
// login
rpc Login(LoginReq) returns (User) {
option (google.api.http) = {
post: "/users",
post: "/login",
body: "*"
};
}
// budgets
rpc AddBudget(AddBudgetReq) returns (Budget) {
option (google.api.http) = {
post: "/budgets",
body: "*"
};
}
rpc UpdateBudget(UpdateBudgetReq) returns (Budget) {
option (google.api.http) = {
put: "/budgets/{id}",
body: "*"
};
}
rpc GetBudgets(GetBudgetsReq) returns (Budgets) {
option (google.api.http) = {
get: "/budgets"
};
}
rpc DeleteBudget(DeleteBudgetReq) returns (Budget) {
option (google.api.http) = {
delete: "/budgets/{id}"
};
}
// budget users
rpc AddUserToBudget(AddUserToBudgetReq) returns (OK) {
option (google.api.http) = {
put: "/budgets/{budget_id}/users",
body: "*"
};
}
rpc GetBudgetUsers(GetBudgetUsersReq) returns (Users) {
option (google.api.http) = {
get: "/budgets/{id}/users"
};
}
rpc RemoveUserFromBudget(RemoveUserFromBudgetReq) returns (Budget) {
option (google.api.http) = {
delete: "/budgets/{budget_id}/users/{user_id}"
};
}
rpc GetBudgetCategories(GetBudgetCategoriesReq) returns (Categories) {
option (google.api.http) = {
get: "/budgets/{budget_id}/categories"
};
}
// categories
rpc AddCategory(CreateCategoryReq) returns (Category) {
rpc AddCategory(AddCategoryReq) returns (Category) {
option (google.api.http) = {
post: "/categories",
body: "*"
@@ -36,9 +85,35 @@ service SmmCore {
put: "/categories/{id}"
};
}
rpc GetCategories(CategoryFilterReq) returns (Categories) {
rpc DeleteCategories(DeleteCategoriesReq) returns (Category) {
option (google.api.http) = {
get: "/categories"
delete: "/categories/{id}"
};
}
// wastes
rpc AddWaste(AddWasteReq) returns (Waste) {
option (google.api.http) = {
post: "/wastes",
body: "*"
};
}
rpc AddWasteByText(AddWasteTextReq) returns (Waste) {
option (google.api.http) = {
post: "/wastes/text",
body: "*"
};
}
rpc DeleteWaste(DeleteWasteReq) returns (Waste) {
option (google.api.http) = {
delete: "/wastes/{id}"
};
}
// stat
rpc GetCategoriesStat(GetCategoriesStatReq) returns (CategoriesStat) {
option (google.api.http) = {
get: "/stat"
};
}
}
@@ -47,8 +122,11 @@ message PingReq {}
message PingRsp {}
message CreateUserReq {
message OK {}
message AddUserReq {
string username = 1;
string password = 2;
}
message User {
@@ -56,12 +134,79 @@ message User {
string username = 2;
}
message CreateCategoryReq {
message LoginReq {
string username = 1;
string password = 2;
}
message AddBudgetReq {
string name = 1;
bool favorite = 2;
int32 start_day = 2;
int32 monthly_limit = 3;
}
message Budget {
int32 id = 1;
string name = 2;
int32 start_day = 3;
int32 monthly_limit = 4;
repeated Category categories = 5;
}
message UpdateBudgetReq {
int32 id = 1;
string name = 2;
int32 start_day = 3;
int32 monthly_limit = 4;
}
message GetBudgetsReq {}
message Budgets {
repeated Budget budgets = 1;
}
message DeleteBudgetReq {
int32 id = 1;
}
message AddUserToBudgetReq {
int32 user_id = 1;
int32 budget_id = 2;
}
message GetBudgetUsersReq {
int32 id = 1;
}
message Users {
repeated User users = 1;
}
message RemoveUserFromBudgetReq {
int32 user_id = 1;
int32 budget_id = 2;
}
message GetBudgetCategoriesReq {
int32 budget_id = 2;
}
message AddCategoryReq {
string name = 1;
int32 budget_id = 2;
bool favorite = 3;
int32 monthly_limit = 4;
}
message Category {
int32 id = 1;
string name = 2;
int32 budget_id = 3;
bool favorite = 4;
int32 monthly_limit = 5;
}
message UpdateCategoryReq {
int32 id = 1;
string name = 2;
@@ -69,17 +214,49 @@ message UpdateCategoryReq {
int32 monthly_limit = 4;
}
message Category {
int32 id = 1;
string name = 2;
bool favorite = 4;
int32 monthly_limit = 5;
}
message CategoryFilterReq {
bool favorite = 1;
}
message Categories {
repeated Category categories = 1;
}
message DeleteCategoriesReq {
int32 id = 1;
}
message AddWasteReq {
string name = 1;
int32 price = 2;
float amount = 3;
int32 category_id = 4;
int32 budget_id = 5;
}
message AddWasteTextReq {
string text = 1;
int32 category_id = 2;
int32 budget_id = 3;
}
message Waste {
int32 id = 1;
string name = 2;
int32 price = 3;
float amount = 4;
}
message DeleteWasteReq {
int32 id = 1;
}
message GetCategoriesStatReq {
repeated int32 ids = 1;
}
message CategoriesStat {
repeated CategoriesStat stat = 1;
}
message CategoryStat {
string name = 1;
int32 monthly_limit = 2;
int32 amount = 3;
}
+35 -2
View File
@@ -9,13 +9,17 @@ import (
"os"
"git.3crabs.ru/save_my_money/smm_core/internal/app"
"git.3crabs.ru/save_my_money/smm_core/internal/services/budget"
"git.3crabs.ru/save_my_money/smm_core/internal/services/category"
"git.3crabs.ru/save_my_money/smm_core/internal/services/user"
"git.3crabs.ru/save_my_money/smm_core/internal/services/waste"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/jackc/pgx/v5/pgxpool"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
proto "git.3crabs.ru/save_my_money/smm_core/proto"
)
@@ -36,11 +40,40 @@ func main() {
categoryService := category.NewCategoryService(dbpool)
userService := user.NewUserService(dbpool)
budgetService := budget.NewBudgetService(dbpool, categoryService)
wasteService := waste.NewWasteService(dbpool, categoryService)
// Create a gRPC server object
s := grpc.NewServer()
s := grpc.NewServer(
grpc.UnaryInterceptor(
func(
ctx context.Context,
req any,
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (resp any, err error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok || len(md["authorization"]) == 0 {
return nil, status.Errorf(codes.Unauthenticated, "no auth token")
}
authToken := md["authorization"][0]
if authToken != os.Getenv("AUTHORIZATION") {
return nil, status.Errorf(codes.Unauthenticated, "invalid token")
}
return handler(ctx, req)
},
),
)
// Attach the Greeter service to the server
proto.RegisterSmmCoreServer(s, app.NewServer(categoryService, userService))
proto.RegisterSmmCoreServer(
s,
app.NewServer(
categoryService,
userService,
budgetService,
wasteService,
),
)
// Serve gRPC server
log.Println("Serving gRPC on 0.0.0.0:8080")
go func() {
+8 -5
View File
@@ -10,15 +10,18 @@ require (
)
require (
github.com/cweill/gotests v1.6.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.7.1 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/crypto v0.29.0 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/net v0.31.0 // indirect
golang.org/x/sync v0.9.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.20.0 // indirect
golang.org/x/tools v0.27.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+23
View File
@@ -1,3 +1,5 @@
github.com/cweill/gotests v1.6.0 h1:KJx+/p4EweijYzqPb4Y/8umDCip1Cv6hEVyOx0mE9W8=
github.com/cweill/gotests v1.6.0/go.mod h1:CaRYbxQZGQOxXDvM9l0XJVV2Tjb2E5H53vq+reR2GrA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@@ -15,18 +17,39 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/tools v0.0.0-20191109212701-97ad0ed33101/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw=
google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38/go.mod h1:vuAjtvlwkDKF6L1GQ0SokiRLCGFfeBUXWr/aFFkHACc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI=
+52
View File
@@ -0,0 +1,52 @@
package app
import (
"git.3crabs.ru/save_my_money/smm_core/internal/services/budget"
"git.3crabs.ru/save_my_money/smm_core/internal/services/category"
"git.3crabs.ru/save_my_money/smm_core/internal/services/user"
"git.3crabs.ru/save_my_money/smm_core/internal/services/waste"
proto "git.3crabs.ru/save_my_money/smm_core/proto"
)
func mapUser(user *user.UserEntity) *proto.User {
return &proto.User{
Id: int32(user.Id),
Username: user.Username,
}
}
func mapBudget(budget *budget.BudgetEntity) *proto.Budget {
return &proto.Budget{
Id: int32(budget.Id),
Name: budget.Name,
StartDay: int32(budget.StartDay),
MonthlyLimit: int32(budget.MonthlyLimit),
Categories: mapCategories(budget.Categories),
}
}
func mapCategory(category *category.CategoryEntity) *proto.Category {
return &proto.Category{
Id: int32(category.Id),
Name: category.Name,
Favorite: category.Favorite,
MonthlyLimit: int32(category.MonthlyLimit),
}
}
func mapCategories(categories []*category.CategoryEntity) []*proto.Category {
res := make([]*proto.Category, 0, len(categories))
for _, item := range categories {
res = append(res, mapCategory(item))
}
return res
}
func mapWaste(waste *waste.WasteEntity) *proto.Waste {
return &proto.Waste{
Id: int32(waste.Id),
Name: waste.Name,
Price: int32(waste.Price),
Amount: waste.Amount,
}
}
+139 -28
View File
@@ -2,83 +2,194 @@ package app
import (
"context"
"errors"
"git.3crabs.ru/save_my_money/smm_core/internal/services/budget"
"git.3crabs.ru/save_my_money/smm_core/internal/services/category"
"git.3crabs.ru/save_my_money/smm_core/internal/services/context_utils"
"git.3crabs.ru/save_my_money/smm_core/internal/services/user"
"git.3crabs.ru/save_my_money/smm_core/internal/services/waste"
proto "git.3crabs.ru/save_my_money/smm_core/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type Server struct {
proto.UnsafeSmmCoreServer
categoryService *category.CategoryService
userService *user.UserService
budgetService *budget.BudgetService
wasteService *waste.WasteService
}
func NewServer(
categoryService *category.CategoryService,
userService *user.UserService,
budgetService *budget.BudgetService,
wasteService *waste.WasteService,
) proto.SmmCoreServer {
return &Server{
categoryService: categoryService,
userService: userService,
budgetService: budgetService,
wasteService: wasteService,
}
}
func (s *Server) Ping(_ context.Context, _ *proto.PingReq) (*proto.PingRsp, error) {
func (s *Server) Ping(context.Context, *proto.PingReq) (*proto.PingRsp, error) {
return &proto.PingRsp{}, nil
}
func (s *Server) AddUser(ctx context.Context, req *proto.CreateUserReq) (*proto.User, error) {
res, err := s.userService.AddUser(
func (s *Server) Login(ctx context.Context, req *proto.LoginReq) (*proto.User, error) {
user, err := s.userService.Login(
ctx,
&user.UserEntity{
Username: req.Username,
Password: req.Password,
},
)
if err != nil {
if errors.Is(err, &user.UsernameAlreadyExistsErr{}) {
return nil, status.Error(codes.AlreadyExists, "Пользователь с таким username уже существует")
}
return nil, err
}
return &proto.User{
Id: int32(res.Id),
Username: res.Username,
return mapUser(user), nil
}
func (s *Server) AddBudget(ctx context.Context, req *proto.AddBudgetReq) (*proto.Budget, error) {
budget, err := s.budgetService.AddBudget(
ctx,
&budget.BudgetEntity{
Name: req.Name,
StartDay: int(req.StartDay),
MonthlyLimit: int(req.MonthlyLimit),
},
)
if err != nil {
return nil, err
}
return mapBudget(budget), nil
}
func (s *Server) GetBudgets(ctx context.Context, req *proto.GetBudgetsReq) (*proto.Budgets, error) {
budgets, err := s.budgetService.GetBudgets(
ctx,
)
if err != nil {
return nil, err
}
res := make([]*proto.Budget, 0, len(budgets))
for _, budget := range budgets {
res = append(res, mapBudget(budget))
}
return &proto.Budgets{
Budgets: res,
}, nil
}
func (s *Server) AddCategory(ctx context.Context, req *proto.CreateCategoryReq) (*proto.Category, error) {
res, err := s.categoryService.AddCategory(
func (s *Server) AddUserToBudget(ctx context.Context, req *proto.AddUserToBudgetReq) (*proto.OK, error) {
_, err := s.budgetService.AddUserToBudget(
ctx,
int(req.BudgetId),
int(req.UserId),
)
if err != nil {
return nil, err
}
return &proto.OK{}, nil
}
func (s *Server) AddCategory(ctx context.Context, req *proto.AddCategoryReq) (*proto.Category, error) {
category, err := s.categoryService.AddCategory(
ctx,
&category.CategoryEntity{
Name: req.Name,
BudgetId: int(req.BudgetId),
Favorite: req.Favorite,
MonthlyLimit: int(req.MonthlyLimit),
},
)
if err != nil {
if errors.Is(err, &context_utils.UnauthorizedErr{}) {
return nil, status.Error(codes.Unauthenticated, "Клиент не авторизован")
}
if errors.Is(err, &category.CategoryAlreadyExistsErr{}) {
return nil, status.Error(codes.AlreadyExists, "Категория с таким именеи уже существует")
}
return nil, err
}
return &proto.Category{
Id: int32(res.Id),
Name: res.Name,
Favorite: res.Favorite,
MonthlyLimit: req.MonthlyLimit,
return mapCategory(category), nil
}
func (s *Server) GetBudgetCategories(ctx context.Context, req *proto.GetBudgetCategoriesReq) (*proto.Categories, error) {
categories, err := s.budgetService.GetBudgetCategories(
ctx,
int(req.BudgetId),
)
if err != nil {
return nil, err
}
res := make([]*proto.Category, 0, len(categories))
for _, category := range categories {
res = append(res, mapCategory(category))
}
return &proto.Categories{
Categories: res,
}, nil
}
// GetCategories implements proto.SmmCoreServer.
func (s *Server) GetCategories(context.Context, *proto.CategoryFilterReq) (*proto.Categories, error) {
func (s *Server) AddWaste(ctx context.Context, req *proto.AddWasteReq) (*proto.Waste, error) {
waste, err := s.wasteService.AddWaste(
ctx,
&waste.WasteEntity{
Name: req.Name,
Price: int(req.Price),
Amount: req.Amount,
CategoryId: int(req.CategoryId),
BudgetId: int(req.BudgetId),
},
)
if err != nil {
return nil, err
}
return mapWaste(waste), nil
}
func (s *Server) AddWasteByText(ctx context.Context, req *proto.AddWasteTextReq) (*proto.Waste, error) {
waste, err := s.wasteService.AddWasteByText(
ctx,
&waste.WasteTextEntity{
Text: req.Text,
CategoryId: int(req.CategoryId),
BudgetId: int(req.BudgetId),
},
)
if err != nil {
return nil, err
}
return mapWaste(waste), nil
}
// GetCategoriesStat implements proto.SmmCoreServer.
func (s *Server) GetCategoriesStat(context.Context, *proto.GetCategoriesStatReq) (*proto.CategoriesStat, error) {
panic("unimplemented")
}
// DeleteBudget implements proto.SmmCoreServer.
func (s *Server) DeleteBudget(context.Context, *proto.DeleteBudgetReq) (*proto.Budget, error) {
panic("unimplemented")
}
// DeleteCategories implements proto.SmmCoreServer.
func (s *Server) DeleteCategories(context.Context, *proto.DeleteCategoriesReq) (*proto.Category, error) {
panic("unimplemented")
}
// DeleteWaste implements proto.SmmCoreServer.
func (s *Server) DeleteWaste(context.Context, *proto.DeleteWasteReq) (*proto.Waste, error) {
panic("unimplemented")
}
// GetBudgetUsers implements proto.SmmCoreServer.
func (s *Server) GetBudgetUsers(context.Context, *proto.GetBudgetUsersReq) (*proto.Users, error) {
panic("unimplemented")
}
// RemoveUserFromBudget implements proto.SmmCoreServer.
func (s *Server) RemoveUserFromBudget(context.Context, *proto.RemoveUserFromBudgetReq) (*proto.Budget, error) {
panic("unimplemented")
}
// UpdateBudget implements proto.SmmCoreServer.
func (s *Server) UpdateBudget(context.Context, *proto.UpdateBudgetReq) (*proto.Budget, error) {
panic("unimplemented")
}
+139
View File
@@ -0,0 +1,139 @@
package budget
import (
"context"
"fmt"
"git.3crabs.ru/save_my_money/smm_core/internal/services/category"
"git.3crabs.ru/save_my_money/smm_core/internal/services/context_utils"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
)
type BudgetEntity struct {
Id int
Name string
StartDay int
MonthlyLimit int
Categories []*category.CategoryEntity
}
type BudgetService struct {
db *pgxpool.Pool
categoryService *category.CategoryService
}
func NewBudgetService(
db *pgxpool.Pool,
categoryService *category.CategoryService,
) *BudgetService {
return &BudgetService{
db: db,
categoryService: categoryService,
}
}
func (s *BudgetService) AddBudget(ctx context.Context, budget *BudgetEntity) (*BudgetEntity, error) {
userId, err := context_utils.GetUserId(ctx)
if err != nil {
return nil, err
}
tx, err := s.db.Begin(ctx)
if err != nil {
return nil, err
}
defer tx.Rollback(ctx)
query := `INSERT INTO budgets (name, start_day, monthly_limit) VALUES (@name, @start_day, @monthly_limit) RETURNING id`
args := pgx.NamedArgs{
"name": budget.Name,
"start_day": budget.StartDay,
"monthly_limit": budget.MonthlyLimit,
}
if err := s.db.QueryRow(ctx, query, args).Scan(&budget.Id); err != nil {
return nil, fmt.Errorf("unable to insert row: %w", err)
}
_, err = s.AddUserToBudget(ctx, budget.Id, userId)
if err != nil {
return nil, err
}
if err = tx.Commit(ctx); err != nil {
return nil, err
}
return budget, nil
}
func (s *BudgetService) GetBudgets(ctx context.Context) ([]*BudgetEntity, error) {
userId, err := context_utils.GetUserId(ctx)
if err != nil {
return nil, err
}
query := `SELECT b.id, b.name, b.start_day, b.monthly_limit FROM budgets b JOIN users_budgets ub ON ub.budget_id = b.id WHERE ub.user_id = @user_id`
args := pgx.NamedArgs{
"user_id": userId,
}
rows, err := s.db.Query(ctx, query, args)
if err != nil {
return nil, err
}
budgets := []*BudgetEntity{}
defer rows.Close()
for rows.Next() {
budget := &BudgetEntity{}
err = rows.Scan(&budget.Id, &budget.Name, &budget.StartDay, &budget.MonthlyLimit)
if err != nil {
return nil, err
}
budget.Categories, err = s.GetBudgetCategories(ctx, budget.Id)
budgets = append(budgets, budget)
}
return budgets, nil
}
func (s *BudgetService) AddUserToBudget(
ctx context.Context,
budgetId int,
userId int,
) (int, error) {
query := `INSERT INTO users_budgets (user_id, budget_id) VALUES (@user_id, @budget_id) RETURNING id`
args := pgx.NamedArgs{
"user_id": userId,
"budget_id": budgetId,
}
id := 0
if err := s.db.QueryRow(ctx, query, args).Scan(&id); err != nil {
return 0, fmt.Errorf("unable to insert row: %w", err)
}
return id, nil
}
func (s *BudgetService) GetBudgetCategories(
ctx context.Context,
budgetId int,
) ([]*category.CategoryEntity, error) {
query := `SELECT id, name, favorite, monthly_limit FROM categories WHERE budget_id = @budget_id`
args := pgx.NamedArgs{
"budget_id": budgetId,
}
rows, err := s.db.Query(ctx, query, args)
if err != nil {
return nil, err
}
categories := []*category.CategoryEntity{}
defer rows.Close()
for rows.Next() {
category := &category.CategoryEntity{}
err = rows.Scan(&category.Id, &category.Name, &category.Favorite, &category.MonthlyLimit)
if err != nil {
return nil, err
}
categories = append(categories, category)
}
return categories, nil
}
+28 -22
View File
@@ -2,29 +2,20 @@ package category
import (
"context"
"errors"
"fmt"
"git.3crabs.ru/save_my_money/smm_core/internal/services/context_utils"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgxpool"
)
type CategoryEntity struct {
Id int
Name string
UserId int
BudgetId int
Favorite bool
MonthlyLimit int
}
type CategoryAlreadyExistsErr struct{}
func (e *CategoryAlreadyExistsErr) Error() string {
return "category already exists error"
}
type CategoryService struct {
db *pgxpool.Pool
}
@@ -38,25 +29,40 @@ func NewCategoryService(
}
func (s *CategoryService) AddCategory(ctx context.Context, category *CategoryEntity) (*CategoryEntity, error) {
userId, err := context_utils.GetUserId(ctx)
if err != nil {
return nil, err
}
query := `INSERT INTO categories (name, user_id, favorite, monthly_limit) VALUES (@name, @user_id, @favorite, @monthly_limit) RETURNING id`
query := `INSERT INTO categories (name, budget_id, favorite, monthly_limit) VALUES (@name, @budget_id, @favorite, @monthly_limit) RETURNING id`
args := pgx.NamedArgs{
"name": category.Name,
"user_id": userId,
"budget_id": category.BudgetId,
"favorite": category.Favorite,
"monthly_limit": category.MonthlyLimit,
}
if err := s.db.QueryRow(ctx, query, args).Scan(&category.Id); err != nil {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
if pgErr.Code == "23505" && pgErr.ConstraintName == "categories_user_id_name_key" { // unique_violation
return nil, &CategoryAlreadyExistsErr{}
}
}
return nil, fmt.Errorf("unable to insert row: %w", err)
}
return category, nil
}
func (s *CategoryService) GetCategory(ctx context.Context, budgetId int, name string) (*CategoryEntity, error) {
query := `SELECT id, name, budget_id, favorite, monthly_limit FROM categories WHERE LOWER(name) = LOWER(@name)`
args := pgx.NamedArgs{
"name": name,
}
rows, err := s.db.Query(ctx, query, args)
if err != nil {
return nil, err
}
categories := []*CategoryEntity{}
defer rows.Close()
for rows.Next() {
category := &CategoryEntity{}
err = rows.Scan(&category.Id, &category.Name, &category.BudgetId, &category.Favorite, &category.MonthlyLimit)
if err != nil {
return nil, err
}
categories = append(categories, category)
}
if len(categories) > 0 {
return categories[0], nil
}
return nil, nil
}
File diff suppressed because one or more lines are too long
+26 -11
View File
@@ -2,17 +2,17 @@ package user
import (
"context"
"errors"
"fmt"
"crypto/md5"
"encoding/hex"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgxpool"
)
type UserEntity struct {
Id int
Username string
Password string
}
type UsernameAlreadyExistsErr struct{}
@@ -21,6 +21,12 @@ func (e *UsernameAlreadyExistsErr) Error() string {
return "username already exists error"
}
type UserNotFoundErr struct{}
func (e *UserNotFoundErr) Error() string {
return "user not found error"
}
type UserService struct {
db *pgxpool.Pool
}
@@ -33,19 +39,28 @@ func NewUserService(
}
}
func (s *UserService) AddUser(ctx context.Context, user *UserEntity) (*UserEntity, error) {
query := `INSERT INTO users (username) VALUES (@username) RETURNING id`
func (s *UserService) Login(ctx context.Context, user *UserEntity) (*UserEntity, error) {
args := pgx.NamedArgs{
"username": user.Username,
"password": hashPassword(user.Username, user.Password, "crab"),
}
query := `SELECT id FROM users WHERE username = @username AND password = @password LIMIT 1`
if err := s.db.QueryRow(ctx, query, args).Scan(&user.Id); err != nil {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
if pgErr.Code == "23505" && pgErr.ConstraintName == "users_username_key" { // unique_violation
return nil, &UsernameAlreadyExistsErr{}
}
query := `INSERT INTO users (username, password) VALUES (@username, @password) RETURNING id`
if err := s.db.QueryRow(ctx, query, args).Scan(&user.Id); err != nil {
return user, err
}
return nil, fmt.Errorf("unable to insert row: %w", err)
}
return user, nil
}
func hashPassword(username string, password string, salt string) string {
return getMD5Hash(username + password + salt)
}
func getMD5Hash(text string) string {
hash := md5.Sum([]byte(text))
return hex.EncodeToString(hash[:])
}
+190
View File
@@ -0,0 +1,190 @@
package waste
import (
"context"
"fmt"
"strconv"
"strings"
"git.3crabs.ru/save_my_money/smm_core/internal/services/category"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
type WasteEntity struct {
Id int
Name string
Price int
Amount float32
CategoryId int
CategoryName string
BudgetId int
}
type WasteTextEntity struct {
Text string
CategoryId int
BudgetId int
}
type WasteService struct {
db *pgxpool.Pool
categoryService *category.CategoryService
}
func NewWasteService(
db *pgxpool.Pool,
categoryService *category.CategoryService,
) *WasteService {
return &WasteService{
db: db,
categoryService: categoryService,
}
}
func (s *WasteService) AddWaste(ctx context.Context, waste *WasteEntity) (*WasteEntity, error) {
query := `INSERT INTO wastes (name, price, amount, budget_id, category_id) VALUES (@name, @price, @amount, @budget_id, @category_id) RETURNING id`
args := pgx.NamedArgs{
"name": waste.Name,
"price": waste.Price,
"amount": waste.Amount,
"budget_id": waste.BudgetId,
"category_id": waste.CategoryId,
}
if err := s.db.QueryRow(ctx, query, args).Scan(&waste.Id); err != nil {
return nil, fmt.Errorf("unable to insert row: %w", err)
}
return waste, nil
}
func (s *WasteService) GetWaste(ctx context.Context, budgetId int, name string) (*WasteEntity, error) {
query := `SELECT id, name, price, amount, budget_id, category_id FROM wastes WHERE budget_id = @budget_id AND LOWER(name) = LOWER(@name) LIMIT 1`
args := pgx.NamedArgs{
"name": name,
"budget_id": budgetId,
}
rows, err := s.db.Query(ctx, query, args)
if err != nil {
return nil, err
}
wastes := []*WasteEntity{}
defer rows.Close()
for rows.Next() {
waste := &WasteEntity{}
err = rows.Scan(&waste.Id, &waste.Name, &waste.Price, &waste.Amount, &waste.BudgetId, &waste.CategoryId)
if err != nil {
return nil, err
}
wastes = append(wastes, waste)
}
if len(wastes) > 0 {
return wastes[0], nil
}
return nil, nil
}
func (s *WasteService) AddWasteByText(ctx context.Context, wasteText *WasteTextEntity) (*WasteEntity, error) {
waste := s.parseWaste(wasteText.Text)
var categoryId *int
if waste.CategoryName != "" {
c, err := s.categoryService.GetCategory(ctx, wasteText.BudgetId, waste.CategoryName)
if err != nil {
return nil, err
}
if c == nil {
c, err = s.categoryService.AddCategory(ctx, &category.CategoryEntity{
Name: waste.CategoryName,
BudgetId: int(wasteText.BudgetId),
})
if err != nil {
return nil, err
}
}
categoryId = &c.Id
}
if categoryId == nil {
w, err := s.GetWaste(ctx, wasteText.BudgetId, waste.Name)
if err != nil {
return nil, err
}
if w != nil {
categoryId = &w.CategoryId
}
}
if categoryId == nil {
return nil, fmt.Errorf("bad request")
}
query := `INSERT INTO wastes (name, price, amount, budget_id, category_id) VALUES (@name, @price, @amount, @budget_id, @category_id) RETURNING id`
args := pgx.NamedArgs{
"name": waste.Name,
"price": waste.Price,
"amount": waste.Amount,
"budget_id": wasteText.BudgetId,
"category_id": *categoryId,
}
if err := s.db.QueryRow(ctx, query, args).Scan(&waste.Id); err != nil {
return nil, fmt.Errorf("unable to insert row: %w", err)
}
return waste, nil
}
func (s *WasteService) parseWaste(text string) *WasteEntity {
text = strings.TrimSpace(text)
arr := strings.Split(text, ":")
waste := &WasteEntity{}
switch len(arr) {
case 1:
arr = strings.Split(strings.TrimSpace(arr[0]), " ")
case 2:
waste.CategoryName = strToName(arr[0])
arr = strings.Split(strings.TrimSpace(arr[1]), " ")
}
switch len(arr) {
case 2:
waste.Name = strToName(arr[0])
waste.Amount = 1
waste.Price = strToPrice(arr[1])
case 3:
waste.Name = strToName(arr[0])
waste.Amount = strToAmount(arr[1])
waste.Price = strToPrice(arr[2])
}
return waste
}
func strToFloat(s string) float32 {
a, err := strconv.ParseFloat(s, 32)
if err != nil {
panic(err)
}
return float32(a)
}
func strToPrice(s string) int {
s = strings.TrimSpace(s)
s = strings.TrimSuffix(s, "/кг")
s = strings.TrimSuffix(s, "/шт")
s = strings.TrimSuffix(s, "р")
s = strings.TrimSuffix(s, "руб")
s = strings.TrimSuffix(s, "рублей")
return int(strToFloat(s) * 100)
}
func strToAmount(s string) float32 {
s = strings.TrimSpace(s)
s = strings.TrimSuffix(s, "шт")
s = strings.TrimSuffix(s, "кг")
return strToFloat(s)
}
func strToName(s string) string {
caser := cases.Title(language.Russian)
return caser.String(strings.TrimSpace(strings.ToLower(s)))
}
@@ -0,0 +1,83 @@
package waste
import (
"reflect"
"testing"
)
func TestWasteService_parseWaste(t *testing.T) {
type args struct {
text string
}
tests := []struct {
name string
args args
want *WasteEntity
}{
{
name: "full",
args: args{
text: "Транспорт: такси 2 200",
},
want: &WasteEntity{
CategoryName: "транспорт",
Name: "такси",
Amount: 2,
Price: 20000,
},
},
{
name: "full without amount",
args: args{
text: "Транспорт: такси 200",
},
want: &WasteEntity{
CategoryName: "транспорт",
Name: "такси",
Amount: 1,
Price: 20000,
},
},
{
name: "without category",
args: args{
text: "такси 2 200",
},
want: &WasteEntity{
Name: "такси",
Amount: 2,
Price: 20000,
},
},
{
name: "without amount",
args: args{
text: "такси 200",
},
want: &WasteEntity{
Name: "такси",
Amount: 1,
Price: 20000,
},
},
{
name: "р",
args: args{
text: "такси 200р",
},
want: &WasteEntity{
Name: "такси",
Amount: 1,
Price: 20000,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &WasteService{}
if got := s.parseWaste(tt.args.text); !reflect.DeepEqual(got, tt.want) {
t.Errorf("WasteService.parseWaste() = %v, want %v", got, tt.want)
}
})
}
}
@@ -2,7 +2,9 @@
-- +goose StatementBegin
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
username TEXT UNIQUE NOT NULL
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
-- +goose StatementEnd
@@ -0,0 +1,15 @@
-- +goose Up
-- +goose StatementBegin
CREATE TABLE IF NOT EXISTS budgets (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
start_day INT NOT NULL,
monthly_limit INT DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW()
);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE IF EXISTS budgets;
-- +goose StatementEnd
@@ -3,10 +3,11 @@
CREATE TABLE IF NOT EXISTS categories (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
user_id INT REFERENCES users(id),
budget_id INT REFERENCES budgets(id) ON DELETE CASCADE,
favorite BOOLEAN DEFAULT FALSE,
monthly_limit INT DEFAULT 0,
UNIQUE (user_id, name)
UNIQUE (budget_id, name),
created_at TIMESTAMP DEFAULT NOW()
);
-- +goose StatementEnd
@@ -0,0 +1,18 @@
-- +goose Up
-- +goose StatementBegin
CREATE TABLE IF NOT EXISTS wastes (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
price INT NOT NULL,
amount FLOAT NOT NULL,
budget_id INT REFERENCES budgets(id) ON DELETE CASCADE,
category_id INT REFERENCES categories(id) ON DELETE RESTRICT,
created_at TIMESTAMP DEFAULT NOW()
);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE IF EXISTS wastes;
-- +goose StatementEnd
А
@@ -0,0 +1,14 @@
-- +goose Up
-- +goose StatementBegin
CREATE TABLE IF NOT EXISTS users_budgets (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id) ON DELETE CASCADE,
budget_id INT REFERENCES budgets(id) ON DELETE RESTRICT,
created_at TIMESTAMP DEFAULT NOW()
);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE IF EXISTS users_budgets;
-- +goose StatementEnd
+1553 -242
View File
File diff suppressed because it is too large Load Diff
+1204 -44
View File
File diff suppressed because it is too large Load Diff
+506 -40
View File
@@ -19,24 +19,53 @@ import (
const _ = grpc.SupportPackageIsVersion9
const (
SmmCore_Ping_FullMethodName = "/crabs.smm_core.SmmCore/Ping"
SmmCore_AddUser_FullMethodName = "/crabs.smm_core.SmmCore/AddUser"
SmmCore_AddCategory_FullMethodName = "/crabs.smm_core.SmmCore/AddCategory"
SmmCore_UpdateCategory_FullMethodName = "/crabs.smm_core.SmmCore/UpdateCategory"
SmmCore_GetCategories_FullMethodName = "/crabs.smm_core.SmmCore/GetCategories"
SmmCore_Ping_FullMethodName = "/crabs.smm_core.SmmCore/Ping"
SmmCore_Login_FullMethodName = "/crabs.smm_core.SmmCore/Login"
SmmCore_AddBudget_FullMethodName = "/crabs.smm_core.SmmCore/AddBudget"
SmmCore_UpdateBudget_FullMethodName = "/crabs.smm_core.SmmCore/UpdateBudget"
SmmCore_GetBudgets_FullMethodName = "/crabs.smm_core.SmmCore/GetBudgets"
SmmCore_DeleteBudget_FullMethodName = "/crabs.smm_core.SmmCore/DeleteBudget"
SmmCore_AddUserToBudget_FullMethodName = "/crabs.smm_core.SmmCore/AddUserToBudget"
SmmCore_GetBudgetUsers_FullMethodName = "/crabs.smm_core.SmmCore/GetBudgetUsers"
SmmCore_RemoveUserFromBudget_FullMethodName = "/crabs.smm_core.SmmCore/RemoveUserFromBudget"
SmmCore_GetBudgetCategories_FullMethodName = "/crabs.smm_core.SmmCore/GetBudgetCategories"
SmmCore_AddCategory_FullMethodName = "/crabs.smm_core.SmmCore/AddCategory"
SmmCore_UpdateCategory_FullMethodName = "/crabs.smm_core.SmmCore/UpdateCategory"
SmmCore_DeleteCategories_FullMethodName = "/crabs.smm_core.SmmCore/DeleteCategories"
SmmCore_AddWaste_FullMethodName = "/crabs.smm_core.SmmCore/AddWaste"
SmmCore_AddWasteByText_FullMethodName = "/crabs.smm_core.SmmCore/AddWasteByText"
SmmCore_DeleteWaste_FullMethodName = "/crabs.smm_core.SmmCore/DeleteWaste"
SmmCore_GetCategoriesStat_FullMethodName = "/crabs.smm_core.SmmCore/GetCategoriesStat"
)
// SmmCoreClient is the client API for SmmCore 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 SmmCoreClient interface {
// ping
Ping(ctx context.Context, in *PingReq, opts ...grpc.CallOption) (*PingRsp, error)
// users
AddUser(ctx context.Context, in *CreateUserReq, opts ...grpc.CallOption) (*User, error)
// login
Login(ctx context.Context, in *LoginReq, opts ...grpc.CallOption) (*User, error)
// budgets
AddBudget(ctx context.Context, in *AddBudgetReq, opts ...grpc.CallOption) (*Budget, error)
UpdateBudget(ctx context.Context, in *UpdateBudgetReq, opts ...grpc.CallOption) (*Budget, error)
GetBudgets(ctx context.Context, in *GetBudgetsReq, opts ...grpc.CallOption) (*Budgets, error)
DeleteBudget(ctx context.Context, in *DeleteBudgetReq, opts ...grpc.CallOption) (*Budget, error)
// budget users
AddUserToBudget(ctx context.Context, in *AddUserToBudgetReq, opts ...grpc.CallOption) (*OK, error)
GetBudgetUsers(ctx context.Context, in *GetBudgetUsersReq, opts ...grpc.CallOption) (*Users, error)
RemoveUserFromBudget(ctx context.Context, in *RemoveUserFromBudgetReq, opts ...grpc.CallOption) (*Budget, error)
GetBudgetCategories(ctx context.Context, in *GetBudgetCategoriesReq, opts ...grpc.CallOption) (*Categories, error)
// categories
AddCategory(ctx context.Context, in *CreateCategoryReq, opts ...grpc.CallOption) (*Category, error)
AddCategory(ctx context.Context, in *AddCategoryReq, opts ...grpc.CallOption) (*Category, error)
UpdateCategory(ctx context.Context, in *UpdateCategoryReq, opts ...grpc.CallOption) (*Category, error)
GetCategories(ctx context.Context, in *CategoryFilterReq, opts ...grpc.CallOption) (*Categories, error)
DeleteCategories(ctx context.Context, in *DeleteCategoriesReq, opts ...grpc.CallOption) (*Category, error)
// wastes
AddWaste(ctx context.Context, in *AddWasteReq, opts ...grpc.CallOption) (*Waste, error)
AddWasteByText(ctx context.Context, in *AddWasteTextReq, opts ...grpc.CallOption) (*Waste, error)
DeleteWaste(ctx context.Context, in *DeleteWasteReq, opts ...grpc.CallOption) (*Waste, error)
// stat
GetCategoriesStat(ctx context.Context, in *GetCategoriesStatReq, opts ...grpc.CallOption) (*CategoriesStat, error)
}
type smmCoreClient struct {
@@ -57,17 +86,97 @@ func (c *smmCoreClient) Ping(ctx context.Context, in *PingReq, opts ...grpc.Call
return out, nil
}
func (c *smmCoreClient) AddUser(ctx context.Context, in *CreateUserReq, opts ...grpc.CallOption) (*User, error) {
func (c *smmCoreClient) Login(ctx context.Context, in *LoginReq, opts ...grpc.CallOption) (*User, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(User)
err := c.cc.Invoke(ctx, SmmCore_AddUser_FullMethodName, in, out, cOpts...)
err := c.cc.Invoke(ctx, SmmCore_Login_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) AddCategory(ctx context.Context, in *CreateCategoryReq, opts ...grpc.CallOption) (*Category, error) {
func (c *smmCoreClient) AddBudget(ctx context.Context, in *AddBudgetReq, opts ...grpc.CallOption) (*Budget, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Budget)
err := c.cc.Invoke(ctx, SmmCore_AddBudget_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) UpdateBudget(ctx context.Context, in *UpdateBudgetReq, opts ...grpc.CallOption) (*Budget, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Budget)
err := c.cc.Invoke(ctx, SmmCore_UpdateBudget_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) GetBudgets(ctx context.Context, in *GetBudgetsReq, opts ...grpc.CallOption) (*Budgets, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Budgets)
err := c.cc.Invoke(ctx, SmmCore_GetBudgets_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) DeleteBudget(ctx context.Context, in *DeleteBudgetReq, opts ...grpc.CallOption) (*Budget, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Budget)
err := c.cc.Invoke(ctx, SmmCore_DeleteBudget_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) AddUserToBudget(ctx context.Context, in *AddUserToBudgetReq, opts ...grpc.CallOption) (*OK, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(OK)
err := c.cc.Invoke(ctx, SmmCore_AddUserToBudget_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) GetBudgetUsers(ctx context.Context, in *GetBudgetUsersReq, opts ...grpc.CallOption) (*Users, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Users)
err := c.cc.Invoke(ctx, SmmCore_GetBudgetUsers_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) RemoveUserFromBudget(ctx context.Context, in *RemoveUserFromBudgetReq, opts ...grpc.CallOption) (*Budget, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Budget)
err := c.cc.Invoke(ctx, SmmCore_RemoveUserFromBudget_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) GetBudgetCategories(ctx context.Context, in *GetBudgetCategoriesReq, opts ...grpc.CallOption) (*Categories, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Categories)
err := c.cc.Invoke(ctx, SmmCore_GetBudgetCategories_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) AddCategory(ctx context.Context, in *AddCategoryReq, opts ...grpc.CallOption) (*Category, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Category)
err := c.cc.Invoke(ctx, SmmCore_AddCategory_FullMethodName, in, out, cOpts...)
@@ -87,10 +196,50 @@ func (c *smmCoreClient) UpdateCategory(ctx context.Context, in *UpdateCategoryRe
return out, nil
}
func (c *smmCoreClient) GetCategories(ctx context.Context, in *CategoryFilterReq, opts ...grpc.CallOption) (*Categories, error) {
func (c *smmCoreClient) DeleteCategories(ctx context.Context, in *DeleteCategoriesReq, opts ...grpc.CallOption) (*Category, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Categories)
err := c.cc.Invoke(ctx, SmmCore_GetCategories_FullMethodName, in, out, cOpts...)
out := new(Category)
err := c.cc.Invoke(ctx, SmmCore_DeleteCategories_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) AddWaste(ctx context.Context, in *AddWasteReq, opts ...grpc.CallOption) (*Waste, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Waste)
err := c.cc.Invoke(ctx, SmmCore_AddWaste_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) AddWasteByText(ctx context.Context, in *AddWasteTextReq, opts ...grpc.CallOption) (*Waste, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Waste)
err := c.cc.Invoke(ctx, SmmCore_AddWasteByText_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) DeleteWaste(ctx context.Context, in *DeleteWasteReq, opts ...grpc.CallOption) (*Waste, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Waste)
err := c.cc.Invoke(ctx, SmmCore_DeleteWaste_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *smmCoreClient) GetCategoriesStat(ctx context.Context, in *GetCategoriesStatReq, opts ...grpc.CallOption) (*CategoriesStat, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CategoriesStat)
err := c.cc.Invoke(ctx, SmmCore_GetCategoriesStat_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -101,13 +250,30 @@ func (c *smmCoreClient) GetCategories(ctx context.Context, in *CategoryFilterReq
// All implementations must embed UnimplementedSmmCoreServer
// for forward compatibility.
type SmmCoreServer interface {
// ping
Ping(context.Context, *PingReq) (*PingRsp, error)
// users
AddUser(context.Context, *CreateUserReq) (*User, error)
// login
Login(context.Context, *LoginReq) (*User, error)
// budgets
AddBudget(context.Context, *AddBudgetReq) (*Budget, error)
UpdateBudget(context.Context, *UpdateBudgetReq) (*Budget, error)
GetBudgets(context.Context, *GetBudgetsReq) (*Budgets, error)
DeleteBudget(context.Context, *DeleteBudgetReq) (*Budget, error)
// budget users
AddUserToBudget(context.Context, *AddUserToBudgetReq) (*OK, error)
GetBudgetUsers(context.Context, *GetBudgetUsersReq) (*Users, error)
RemoveUserFromBudget(context.Context, *RemoveUserFromBudgetReq) (*Budget, error)
GetBudgetCategories(context.Context, *GetBudgetCategoriesReq) (*Categories, error)
// categories
AddCategory(context.Context, *CreateCategoryReq) (*Category, error)
AddCategory(context.Context, *AddCategoryReq) (*Category, error)
UpdateCategory(context.Context, *UpdateCategoryReq) (*Category, error)
GetCategories(context.Context, *CategoryFilterReq) (*Categories, error)
DeleteCategories(context.Context, *DeleteCategoriesReq) (*Category, error)
// wastes
AddWaste(context.Context, *AddWasteReq) (*Waste, error)
AddWasteByText(context.Context, *AddWasteTextReq) (*Waste, error)
DeleteWaste(context.Context, *DeleteWasteReq) (*Waste, error)
// stat
GetCategoriesStat(context.Context, *GetCategoriesStatReq) (*CategoriesStat, error)
mustEmbedUnimplementedSmmCoreServer()
}
@@ -121,17 +287,53 @@ type UnimplementedSmmCoreServer struct{}
func (UnimplementedSmmCoreServer) Ping(context.Context, *PingReq) (*PingRsp, error) {
return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented")
}
func (UnimplementedSmmCoreServer) AddUser(context.Context, *CreateUserReq) (*User, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddUser not implemented")
func (UnimplementedSmmCoreServer) Login(context.Context, *LoginReq) (*User, error) {
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
}
func (UnimplementedSmmCoreServer) AddCategory(context.Context, *CreateCategoryReq) (*Category, error) {
func (UnimplementedSmmCoreServer) AddBudget(context.Context, *AddBudgetReq) (*Budget, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddBudget not implemented")
}
func (UnimplementedSmmCoreServer) UpdateBudget(context.Context, *UpdateBudgetReq) (*Budget, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateBudget not implemented")
}
func (UnimplementedSmmCoreServer) GetBudgets(context.Context, *GetBudgetsReq) (*Budgets, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetBudgets not implemented")
}
func (UnimplementedSmmCoreServer) DeleteBudget(context.Context, *DeleteBudgetReq) (*Budget, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteBudget not implemented")
}
func (UnimplementedSmmCoreServer) AddUserToBudget(context.Context, *AddUserToBudgetReq) (*OK, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddUserToBudget not implemented")
}
func (UnimplementedSmmCoreServer) GetBudgetUsers(context.Context, *GetBudgetUsersReq) (*Users, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetBudgetUsers not implemented")
}
func (UnimplementedSmmCoreServer) RemoveUserFromBudget(context.Context, *RemoveUserFromBudgetReq) (*Budget, error) {
return nil, status.Errorf(codes.Unimplemented, "method RemoveUserFromBudget not implemented")
}
func (UnimplementedSmmCoreServer) GetBudgetCategories(context.Context, *GetBudgetCategoriesReq) (*Categories, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetBudgetCategories not implemented")
}
func (UnimplementedSmmCoreServer) AddCategory(context.Context, *AddCategoryReq) (*Category, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddCategory not implemented")
}
func (UnimplementedSmmCoreServer) UpdateCategory(context.Context, *UpdateCategoryReq) (*Category, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateCategory not implemented")
}
func (UnimplementedSmmCoreServer) GetCategories(context.Context, *CategoryFilterReq) (*Categories, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetCategories not implemented")
func (UnimplementedSmmCoreServer) DeleteCategories(context.Context, *DeleteCategoriesReq) (*Category, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteCategories not implemented")
}
func (UnimplementedSmmCoreServer) AddWaste(context.Context, *AddWasteReq) (*Waste, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddWaste not implemented")
}
func (UnimplementedSmmCoreServer) AddWasteByText(context.Context, *AddWasteTextReq) (*Waste, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddWasteByText not implemented")
}
func (UnimplementedSmmCoreServer) DeleteWaste(context.Context, *DeleteWasteReq) (*Waste, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteWaste not implemented")
}
func (UnimplementedSmmCoreServer) GetCategoriesStat(context.Context, *GetCategoriesStatReq) (*CategoriesStat, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetCategoriesStat not implemented")
}
func (UnimplementedSmmCoreServer) mustEmbedUnimplementedSmmCoreServer() {}
func (UnimplementedSmmCoreServer) testEmbeddedByValue() {}
@@ -172,26 +374,170 @@ func _SmmCore_Ping_Handler(srv interface{}, ctx context.Context, dec func(interf
return interceptor(ctx, in, info, handler)
}
func _SmmCore_AddUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateUserReq)
func _SmmCore_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LoginReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).AddUser(ctx, in)
return srv.(SmmCoreServer).Login(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_AddUser_FullMethodName,
FullMethod: SmmCore_Login_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).AddUser(ctx, req.(*CreateUserReq))
return srv.(SmmCoreServer).Login(ctx, req.(*LoginReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_AddBudget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AddBudgetReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).AddBudget(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_AddBudget_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).AddBudget(ctx, req.(*AddBudgetReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_UpdateBudget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateBudgetReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).UpdateBudget(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_UpdateBudget_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).UpdateBudget(ctx, req.(*UpdateBudgetReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_GetBudgets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetBudgetsReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).GetBudgets(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_GetBudgets_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).GetBudgets(ctx, req.(*GetBudgetsReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_DeleteBudget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteBudgetReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).DeleteBudget(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_DeleteBudget_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).DeleteBudget(ctx, req.(*DeleteBudgetReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_AddUserToBudget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AddUserToBudgetReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).AddUserToBudget(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_AddUserToBudget_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).AddUserToBudget(ctx, req.(*AddUserToBudgetReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_GetBudgetUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetBudgetUsersReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).GetBudgetUsers(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_GetBudgetUsers_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).GetBudgetUsers(ctx, req.(*GetBudgetUsersReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_RemoveUserFromBudget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RemoveUserFromBudgetReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).RemoveUserFromBudget(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_RemoveUserFromBudget_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).RemoveUserFromBudget(ctx, req.(*RemoveUserFromBudgetReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_GetBudgetCategories_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetBudgetCategoriesReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).GetBudgetCategories(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_GetBudgetCategories_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).GetBudgetCategories(ctx, req.(*GetBudgetCategoriesReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_AddCategory_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateCategoryReq)
in := new(AddCategoryReq)
if err := dec(in); err != nil {
return nil, err
}
@@ -203,7 +549,7 @@ func _SmmCore_AddCategory_Handler(srv interface{}, ctx context.Context, dec func
FullMethod: SmmCore_AddCategory_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).AddCategory(ctx, req.(*CreateCategoryReq))
return srv.(SmmCoreServer).AddCategory(ctx, req.(*AddCategoryReq))
}
return interceptor(ctx, in, info, handler)
}
@@ -226,20 +572,92 @@ func _SmmCore_UpdateCategory_Handler(srv interface{}, ctx context.Context, dec f
return interceptor(ctx, in, info, handler)
}
func _SmmCore_GetCategories_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CategoryFilterReq)
func _SmmCore_DeleteCategories_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteCategoriesReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).GetCategories(ctx, in)
return srv.(SmmCoreServer).DeleteCategories(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_GetCategories_FullMethodName,
FullMethod: SmmCore_DeleteCategories_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).GetCategories(ctx, req.(*CategoryFilterReq))
return srv.(SmmCoreServer).DeleteCategories(ctx, req.(*DeleteCategoriesReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_AddWaste_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AddWasteReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).AddWaste(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_AddWaste_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).AddWaste(ctx, req.(*AddWasteReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_AddWasteByText_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AddWasteTextReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).AddWasteByText(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_AddWasteByText_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).AddWasteByText(ctx, req.(*AddWasteTextReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_DeleteWaste_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteWasteReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).DeleteWaste(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_DeleteWaste_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).DeleteWaste(ctx, req.(*DeleteWasteReq))
}
return interceptor(ctx, in, info, handler)
}
func _SmmCore_GetCategoriesStat_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetCategoriesStatReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SmmCoreServer).GetCategoriesStat(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SmmCore_GetCategoriesStat_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SmmCoreServer).GetCategoriesStat(ctx, req.(*GetCategoriesStatReq))
}
return interceptor(ctx, in, info, handler)
}
@@ -256,8 +674,40 @@ var SmmCore_ServiceDesc = grpc.ServiceDesc{
Handler: _SmmCore_Ping_Handler,
},
{
MethodName: "AddUser",
Handler: _SmmCore_AddUser_Handler,
MethodName: "Login",
Handler: _SmmCore_Login_Handler,
},
{
MethodName: "AddBudget",
Handler: _SmmCore_AddBudget_Handler,
},
{
MethodName: "UpdateBudget",
Handler: _SmmCore_UpdateBudget_Handler,
},
{
MethodName: "GetBudgets",
Handler: _SmmCore_GetBudgets_Handler,
},
{
MethodName: "DeleteBudget",
Handler: _SmmCore_DeleteBudget_Handler,
},
{
MethodName: "AddUserToBudget",
Handler: _SmmCore_AddUserToBudget_Handler,
},
{
MethodName: "GetBudgetUsers",
Handler: _SmmCore_GetBudgetUsers_Handler,
},
{
MethodName: "RemoveUserFromBudget",
Handler: _SmmCore_RemoveUserFromBudget_Handler,
},
{
MethodName: "GetBudgetCategories",
Handler: _SmmCore_GetBudgetCategories_Handler,
},
{
MethodName: "AddCategory",
@@ -268,8 +718,24 @@ var SmmCore_ServiceDesc = grpc.ServiceDesc{
Handler: _SmmCore_UpdateCategory_Handler,
},
{
MethodName: "GetCategories",
Handler: _SmmCore_GetCategories_Handler,
MethodName: "DeleteCategories",
Handler: _SmmCore_DeleteCategories_Handler,
},
{
MethodName: "AddWaste",
Handler: _SmmCore_AddWaste_Handler,
},
{
MethodName: "AddWasteByText",
Handler: _SmmCore_AddWasteByText_Handler,
},
{
MethodName: "DeleteWaste",
Handler: _SmmCore_DeleteWaste_Handler,
},
{
MethodName: "GetCategoriesStat",
Handler: _SmmCore_GetCategoriesStat_Handler,
},
},
Streams: []grpc.StreamDesc{},
+619 -46
View File
@@ -16,9 +16,62 @@
"application/json"
],
"paths": {
"/categories": {
"/budgets": {
"get": {
"operationId": "SmmCore_GetCategories",
"operationId": "SmmCore_GetBudgets",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_coreBudgets"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"SmmCore"
]
},
"post": {
"summary": "budgets",
"operationId": "SmmCore_AddBudget",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_coreBudget"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/smm_coreAddBudgetReq"
}
}
],
"tags": [
"SmmCore"
]
}
},
"/budgets/{budgetId}/categories": {
"get": {
"operationId": "SmmCore_GetBudgetCategories",
"responses": {
"200": {
"description": "A successful response.",
@@ -35,16 +88,196 @@
},
"parameters": [
{
"name": "favorite",
"in": "query",
"required": false,
"type": "boolean"
"name": "budgetId",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
}
],
"tags": [
"SmmCore"
]
}
},
"/budgets/{budgetId}/users": {
"put": {
"summary": "budget users",
"operationId": "SmmCore_AddUserToBudget",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_coreOK"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "budgetId",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/SmmCoreAddUserToBudgetBody"
}
}
],
"tags": [
"SmmCore"
]
}
},
"/budgets/{budgetId}/users/{userId}": {
"delete": {
"operationId": "SmmCore_RemoveUserFromBudget",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_coreBudget"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "budgetId",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
},
{
"name": "userId",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
}
],
"tags": [
"SmmCore"
]
}
},
"/budgets/{id}": {
"delete": {
"operationId": "SmmCore_DeleteBudget",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_coreBudget"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
}
],
"tags": [
"SmmCore"
]
},
"put": {
"operationId": "SmmCore_UpdateBudget",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_coreBudget"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/SmmCoreUpdateBudgetBody"
}
}
],
"tags": [
"SmmCore"
]
}
},
"/budgets/{id}/users": {
"get": {
"operationId": "SmmCore_GetBudgetUsers",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_coreUsers"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
}
],
"tags": [
"SmmCore"
]
}
},
"/categories": {
"post": {
"summary": "categories",
"operationId": "SmmCore_AddCategory",
@@ -68,7 +301,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/smm_coreCreateCategoryReq"
"$ref": "#/definitions/smm_coreAddCategoryReq"
}
}
],
@@ -78,6 +311,35 @@
}
},
"/categories/{id}": {
"delete": {
"operationId": "SmmCore_DeleteCategories",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_coreCategory"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
}
],
"tags": [
"SmmCore"
]
},
"put": {
"operationId": "SmmCore_UpdateCategory",
"responses": {
@@ -127,32 +389,10 @@
]
}
},
"/ping": {
"get": {
"operationId": "SmmCore_Ping",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_corePingRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"SmmCore"
]
}
},
"/users": {
"/login": {
"post": {
"summary": "users",
"operationId": "SmmCore_AddUser",
"summary": "login",
"operationId": "SmmCore_Login",
"responses": {
"200": {
"description": "A successful response.",
@@ -173,7 +413,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/smm_coreCreateUserReq"
"$ref": "#/definitions/smm_coreLoginReq"
}
}
],
@@ -181,9 +421,189 @@
"SmmCore"
]
}
},
"/ping": {
"get": {
"summary": "ping",
"operationId": "SmmCore_Ping",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_corePingRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"SmmCore"
]
}
},
"/stat": {
"get": {
"summary": "stat",
"operationId": "SmmCore_GetCategoriesStat",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_coreCategoriesStat"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "ids",
"in": "query",
"required": false,
"type": "array",
"items": {
"type": "integer",
"format": "int32"
},
"collectionFormat": "multi"
}
],
"tags": [
"SmmCore"
]
}
},
"/wastes": {
"post": {
"summary": "wastes",
"operationId": "SmmCore_AddWaste",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_coreWaste"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/smm_coreAddWasteReq"
}
}
],
"tags": [
"SmmCore"
]
}
},
"/wastes/text": {
"post": {
"operationId": "SmmCore_AddWasteByText",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_coreWaste"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/smm_coreAddWasteTextReq"
}
}
],
"tags": [
"SmmCore"
]
}
},
"/wastes/{id}": {
"delete": {
"operationId": "SmmCore_DeleteWaste",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/smm_coreWaste"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
}
],
"tags": [
"SmmCore"
]
}
}
},
"definitions": {
"SmmCoreAddUserToBudgetBody": {
"type": "object",
"properties": {
"userId": {
"type": "integer",
"format": "int32"
}
}
},
"SmmCoreUpdateBudgetBody": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"startDay": {
"type": "integer",
"format": "int32"
},
"monthlyLimit": {
"type": "integer",
"format": "int32"
}
}
},
"protobufAny": {
"type": "object",
"properties": {
@@ -212,6 +632,120 @@
}
}
},
"smm_coreAddBudgetReq": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"startDay": {
"type": "integer",
"format": "int32"
},
"monthlyLimit": {
"type": "integer",
"format": "int32"
}
}
},
"smm_coreAddCategoryReq": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"budgetId": {
"type": "integer",
"format": "int32"
},
"favorite": {
"type": "boolean"
},
"monthlyLimit": {
"type": "integer",
"format": "int32"
}
}
},
"smm_coreAddWasteReq": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"price": {
"type": "integer",
"format": "int32"
},
"amount": {
"type": "number",
"format": "float"
},
"categoryId": {
"type": "integer",
"format": "int32"
},
"budgetId": {
"type": "integer",
"format": "int32"
}
}
},
"smm_coreAddWasteTextReq": {
"type": "object",
"properties": {
"text": {
"type": "string"
},
"categoryId": {
"type": "integer",
"format": "int32"
},
"budgetId": {
"type": "integer",
"format": "int32"
}
}
},
"smm_coreBudget": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int32"
},
"name": {
"type": "string"
},
"startDay": {
"type": "integer",
"format": "int32"
},
"monthlyLimit": {
"type": "integer",
"format": "int32"
},
"categories": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/smm_coreCategory"
}
}
}
},
"smm_coreBudgets": {
"type": "object",
"properties": {
"budgets": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/smm_coreBudget"
}
}
}
},
"smm_coreCategories": {
"type": "object",
"properties": {
@@ -224,6 +758,18 @@
}
}
},
"smm_coreCategoriesStat": {
"type": "object",
"properties": {
"stat": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/smm_coreCategoriesStat"
}
}
}
},
"smm_coreCategory": {
"type": "object",
"properties": {
@@ -234,20 +780,9 @@
"name": {
"type": "string"
},
"favorite": {
"type": "boolean"
},
"monthlyLimit": {
"budgetId": {
"type": "integer",
"format": "int32"
}
}
},
"smm_coreCreateCategoryReq": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"favorite": {
"type": "boolean"
@@ -258,14 +793,20 @@
}
}
},
"smm_coreCreateUserReq": {
"smm_coreLoginReq": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
}
}
},
"smm_coreOK": {
"type": "object"
},
"smm_corePingRsp": {
"type": "object"
},
@@ -280,6 +821,38 @@
"type": "string"
}
}
},
"smm_coreUsers": {
"type": "object",
"properties": {
"users": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/smm_coreUser"
}
}
}
},
"smm_coreWaste": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int32"
},
"name": {
"type": "string"
},
"price": {
"type": "integer",
"format": "int32"
},
"amount": {
"type": "number",
"format": "float"
}
}
}
}
}
+1
View File
@@ -0,0 +1 @@
SELECT b.id, b.name, b.start_day, b.monthly_limit FROM budgets b JOIN users_budgets ub ON ub.budget_id = b.id WHERE ub.user_id = 1;