This commit is contained in:
2024-11-20 23:26:51 +07:00
parent 6c99309caf
commit ee3e10d46d
11 changed files with 126 additions and 84 deletions
+22 -4
View File
@@ -2,9 +2,12 @@ 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"
)
@@ -16,6 +19,12 @@ type CategoryEntity struct {
MonthlyLimit int
}
type CategoryAlreadyExistsErr struct{}
func (e *CategoryAlreadyExistsErr) Error() string {
return "category already exists error"
}
type CategoryService struct {
db *pgxpool.Pool
}
@@ -29,15 +38,24 @@ func NewCategoryService(
}
func (s *CategoryService) AddCategory(ctx context.Context, category *CategoryEntity) (*CategoryEntity, error) {
query := `INSERT INTO categories (name, user_id, favorite, monthly_limit) VALUES (@name, @user_id, @favorite, @monthly_limit)`
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`
args := pgx.NamedArgs{
"name": category.Name,
"user_id": 1,
"user_id": userId,
"favorite": category.Favorite,
"monthly_limit": category.MonthlyLimit,
}
_, err := s.db.Exec(ctx, query, args)
if err != nil {
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
@@ -1 +0,0 @@
[{"kind":1,"language":"markdown","value":"# Добавление категории","outputs":[]},{"kind":2,"language":"rest-book","value":"POST http://localhost:8090/categories\n\n{\n \"name\": \"Продукты питания\",\n \"favorite\": true,\n \"monthlyLimit\": 5000\n}","outputs":[{"mime":"x-application/rest-book","value":{"status":200,"statusText":"OK","headers":{"Date":"Tue, 19 Nov 2024 15:43:01 GMT","Content-Type":"application/json","Content-Length":"88"},"config":{"timeout":10000,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json","User-Agent":"rest-book","Content-Length":78}},"request":{"method":"POST","httpVersion":"1.1","responseUrl":"http://localhost:8090/categories","timeout":10000,"headers":{"User-Agent":"rest-book"},"data":{"name":"Продукты питания","favorite":true,"monthlyLimit":5000}},"data":{"id":0,"name":"Продукты питания","favorite":true,"monthlyLimit":5000}}},{"mime":"text/x-json","value":{"status":200,"statusText":"OK","headers":{"Date":"Tue, 19 Nov 2024 15:43:01 GMT","Content-Type":"application/json","Content-Length":"88"},"config":{"timeout":10000,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json","User-Agent":"rest-book","Content-Length":78}},"request":{"method":"POST","httpVersion":"1.1","responseUrl":"http://localhost:8090/categories","timeout":10000,"headers":{"User-Agent":"rest-book"},"data":{"name":"Продукты питания","favorite":true,"monthlyLimit":5000}},"data":{"id":0,"name":"Продукты питания","favorite":true,"monthlyLimit":5000}}},{"mime":"text/html","value":"[object Object]"}]}]
@@ -0,0 +1,26 @@
package context_utils
import (
"context"
"strconv"
"google.golang.org/grpc/metadata"
)
type UnauthorizedErr struct{}
func (e *UnauthorizedErr) Error() string {
return "user not autorize"
}
func GetUserId(ctx context.Context) (int, error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return 0, &UnauthorizedErr{}
}
id, err := strconv.Atoi(md["user-id"][0])
if err != nil {
return 0, &UnauthorizedErr{}
}
return id, nil
}
+1
View File
@@ -0,0 +1 @@
[{"kind":1,"language":"markdown","value":"# Добавление пользователя","outputs":[]},{"kind":2,"language":"rest-book","value":"POST http://localhost:8090/users\n\n{\n \"username\": \"foo\"\n}","outputs":[{"mime":"x-application/rest-book","value":{"status":200,"statusText":"OK","headers":{"Date":"Wed, 20 Nov 2024 16:14:45 GMT","Content-Type":"application/json","Content-Length":"25"},"config":{"timeout":10000,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json","User-Agent":"rest-book","Content-Length":18}},"request":{"method":"POST","httpVersion":"1.1","responseUrl":"http://localhost:8090/users","timeout":10000,"headers":{"User-Agent":"rest-book"},"data":{"username":"foo"}},"data":{"id":1,"username":"foo"}}},{"mime":"text/x-json","value":{"status":200,"statusText":"OK","headers":{"Date":"Wed, 20 Nov 2024 16:14:45 GMT","Content-Type":"application/json","Content-Length":"25"},"config":{"timeout":10000,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json","User-Agent":"rest-book","Content-Length":18}},"request":{"method":"POST","httpVersion":"1.1","responseUrl":"http://localhost:8090/users","timeout":10000,"headers":{"User-Agent":"rest-book"},"data":{"username":"foo"}},"data":{"id":1,"username":"foo"}}},{"mime":"text/html","value":"[object Object]"}]},{"kind":1,"language":"markdown","value":"# Добавление категории","outputs":[]},{"kind":2,"language":"rest-book","value":"POST http://localhost:8090/categories\nUser-Id: 1\n\n{\n \"name\": \"Продукты питания\"\n}","outputs":[{"mime":"x-application/rest-book","value":{"status":500,"statusText":"Internal Server Error","headers":{"Date":"Wed, 20 Nov 2024 16:25:26 GMT","Content-Type":"application/json","Content-Length":"184"},"config":{"timeout":10000,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json","User-Id":"2","User-Agent":"axios/0.21.4","Content-Length":42}},"request":{"method":"POST","httpVersion":"1.1","responseUrl":"http://localhost:8090/categories","timeout":10000,"headers":{"User-Id":"2"},"data":{"name":"Продукты питания"}},"data":{"code":2,"message":"unable to insert row: ERROR: insert or update on table \"categories\" violates foreign key constraint \"categories_user_id_fkey\" (SQLSTATE 23503)","details":[]}}},{"mime":"text/x-json","value":{"status":500,"statusText":"Internal Server Error","headers":{"Date":"Wed, 20 Nov 2024 16:25:26 GMT","Content-Type":"application/json","Content-Length":"184"},"config":{"timeout":10000,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json","User-Id":"2","User-Agent":"axios/0.21.4","Content-Length":42}},"request":{"method":"POST","httpVersion":"1.1","responseUrl":"http://localhost:8090/categories","timeout":10000,"headers":{"User-Id":"2"},"data":{"name":"Продукты питания"}},"data":{"code":2,"message":"unable to insert row: ERROR: insert or update on table \"categories\" violates foreign key constraint \"categories_user_id_fkey\" (SQLSTATE 23503)","details":[]}}},{"mime":"text/html","value":"[object Object]"}]}]
-1
View File
@@ -1 +0,0 @@
[{"kind":1,"language":"markdown","value":"# Добавление пользователя","outputs":[]},{"kind":2,"language":"rest-book","value":"POST http://localhost:8090/users\n\n{\n \"username\": \"foo\"\n}","outputs":[{"mime":"x-application/rest-book","value":{"status":409,"statusText":"Conflict","headers":{"Date":"Wed, 20 Nov 2024 08:30:32 GMT","Content-Type":"application/json","Content-Length":"111"},"config":{"timeout":10000,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json","User-Agent":"rest-book","Content-Length":18}},"request":{"method":"POST","httpVersion":"1.1","responseUrl":"http://localhost:8090/users","timeout":10000,"headers":{"User-Agent":"rest-book"},"data":{"username":"bar"}},"data":{"code":6,"message":"Пользователь с таким username уже существует","details":[]}}},{"mime":"text/x-json","value":{"status":409,"statusText":"Conflict","headers":{"Date":"Wed, 20 Nov 2024 08:30:32 GMT","Content-Type":"application/json","Content-Length":"111"},"config":{"timeout":10000,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json","User-Agent":"rest-book","Content-Length":18}},"request":{"method":"POST","httpVersion":"1.1","responseUrl":"http://localhost:8090/users","timeout":10000,"headers":{"User-Agent":"rest-book"},"data":{"username":"bar"}},"data":{"code":6,"message":"Пользователь с таким username уже существует","details":[]}}},{"mime":"text/html","value":"[object Object]"}]}]