Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Review PR #9

Open
wants to merge 72 commits into
base: review
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
1833868
go.mod
Mar 6, 2023
f3db08d
1 | draw the model
Mar 13, 2023
5a8f01b
1 | fix the module name
Mar 13, 2023
f561e3b
1 | get gin framework, log and test packages
Mar 13, 2023
4cb736d
1 | set up db
Mar 13, 2023
029620c
2 | WIP | register endpoint
Mar 13, 2023
0790254
2 | WIP | upsertUser
Mar 13, 2023
0c1e19d
2 | WIP | при регистрации проверяем что пользователь еще не создан
Mar 13, 2023
e63748c
2 | логер, hash generator и другое
Mar 14, 2023
cb4b3a9
2 | чтобы можно работать полностью в docker
Mar 15, 2023
cf6150f
3| login and authorization
Mar 15, 2023
614b4ba
3| доделал метод сервиса
Mar 16, 2023
d95143b
3| refactoring
Mar 16, 2023
fab7073
3| refactoring 2
Mar 16, 2023
20e39b4
3| refactoring 3
Mar 16, 2023
82c86e6
3| refactoring 4
Mar 16, 2023
55fe0db
3| refactoring 5
Mar 16, 2023
5123de1
Merge pull request #1 from smamykin/3-login
smamykin Mar 16, 2023
2758eed
4 | фикс статического анализа
Mar 16, 2023
2fe7cb2
4 | переименовал env переменные как в автотестах
Mar 16, 2023
3aa61b6
4 | судя по всему миграции придется накатывать во время старта, чтобы…
Mar 16, 2023
5307d81
4 | для метода register возвращаем сразу заголовок авторизации
Mar 16, 2023
7ab9b42
4 | clean up
Mar 16, 2023
49aa92c
Merge pull request #2 from smamykin/4-fix-ci
smamykin Mar 16, 2023
0633efe
5 | WIP
Mar 16, 2023
b91fe4f
5 | переименование db store -> user_repository
Mar 17, 2023
4b627b3
5 | доделан POST order endpoint
Mar 17, 2023
57fd5be
Merge pull request #3 from smamykin/5-order-post
smamykin Mar 17, 2023
abdc275
6 | order list
Mar 17, 2023
33daee8
6 | order list
Mar 17, 2023
9ff359b
6 | пытаюсь фиксануть ошибку в автотестах CI
Mar 17, 2023
538c095
6 | фиксим статус для POST order
Mar 17, 2023
42ec755
6 | алогоритм Луна
Mar 17, 2023
6b860dc
6 | поправил статусы
Mar 17, 2023
808bdba
6 | поправил статусы
Mar 17, 2023
1cd6d99
Merge pull request #4 from smamykin/6-order_list
smamykin Mar 17, 2023
aaf9dcf
7 | метод обновления статусов в order_service
Mar 17, 2023
6a97406
7 | accrual to docker-compose
Mar 18, 2023
143d9b8
7 | accraul client
Mar 18, 2023
2c6da6b
7 | creating go routine
Mar 18, 2023
ba1ff4d
7 | методы в репозиториях
Mar 18, 2023
5b09117
7 | поправил ошибки при запуске update statuses рутины
Mar 18, 2023
b5d4145
7 | CI тесты - почему то null pointer на логене
Mar 18, 2023
858d27a
7 | CI test - оказывается accrual не инт, а float
Mar 18, 2023
3e96c60
7 | ошибка в записи Accrual значения
Mar 18, 2023
01986b9
Merge pull request #5 from smamykin/7-update-statuses
smamykin Mar 18, 2023
d9ecc2b
8 | актуализация черновика
Mar 18, 2023
0c741fb
8 | balance
Mar 18, 2023
88989ac
8 | CI fix
Mar 18, 2023
453aae3
8 | CI fix
Mar 18, 2023
ba5aeb6
Merge pull request #6 from smamykin/8-balance
smamykin Mar 18, 2023
ad22b5c
9 | добавил номер заказа
Mar 18, 2023
348f1ae
9 | withdraw
Mar 18, 2023
433ad7f
9 | ci fix
Mar 18, 2023
fec5d9f
Merge pull request #7 from smamykin/9-withdraw
smamykin Mar 19, 2023
9f88892
10 | withdrawal list
Mar 19, 2023
8bdb9fd
10 | поправил название поля для номера заказа
Mar 19, 2023
4f49417
Merge pull request #8 from smamykin/10-withdrawal_list
smamykin Mar 19, 2023
8e6e530
11 | review | если заказ не зарегистрирован в accrual, то возвращаем …
Mar 24, 2023
d165648
11 | вынес установку и получение currentUserID в отдельный методы
Mar 24, 2023
3a61c2a
11 | вместо trace ошибки добавил возможность передать сообщение
Mar 24, 2023
57bbd76
11 | уменьшение вложенности в контроллере
Mar 24, 2023
a8be0c1
11 | заменил сравнение ошибок и .JSON на .AbortWithStatusJSON в неуда…
Mar 24, 2023
1542be7
11 | добавил логирование там где возвращаем статус "service unavailable"
Mar 24, 2023
2d72545
11 | заменил панику на возврат ошибки при получении ID текущего польз…
Mar 24, 2023
88679cc
11 | удалил методы гидраторы
Mar 24, 2023
2a0c1a4
11 | fix - в case можно использовать несколько значений
Mar 24, 2023
f275e01
11 | InvokeFunctionWithInterval работает с конеткстом
Mar 24, 2023
7681b1e
11 | accrual & amount нужно делать через int, хоть у нас и нет делени…
Mar 24, 2023
1d44802
11 | ci recommendations
Mar 24, 2023
4d7cabc
Merge pull request #10 from smamykin/11-review
smamykin Mar 24, 2023
f219408
11 | добавил images + пофиксил zerolog_adapter.go
Mar 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ cmd/gophermart/gophermart

# Dependency directories (remove the comment below to include it)
vendor/
build/*

# IDEs directories
.idea
Expand Down
212 changes: 212 additions & 0 deletions DRAFT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
# Gofermart

## Use cases

![Use cases](./use_cases.png "Use cases")
<details>
<summary>plant uml code of image</summary>

```puml
Copy link
Collaborator Author

@Barugoo Barugoo Mar 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Очень круто что ты сделал диаграмы, но имхо было бы лучше если бы ты здесь просто отрендереную картинку бы вставил тк в текущем виде приходится идти в стороннюю софтину чтобы это посмотреть(

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

@startuml
skinparam actorStyle awesome

legend right
| Color | Mean |
| | to implement |
|<#lightyellow> | are not in the task |
endlegend

left to right direction

actor "User" as U

package "Система лояльности" as M {
usecase "регистрация/авторизация" as M_RA
usecase "отправить номер заказа"as M_SON
usecase "получить статус начисления по заказу" as M_GOS
usecase "списать балы" as M_DB
usecase "получить все списания" as M_DH
}

package "Система расчетов балов(aka accrual)" as ACR #lightyellow {
usecase "Зарегестрировать номер заказа" as A_RON
usecase "Расчитать балы лояльности по заказу" as A_CB
}
package "Online shop" as OS #lightyellow {
usecase "Купить" as OS_B
}

U ..> M_RA : 3
U ..> M_SON : 4
M_SON ..> A_CB : 5
U ..> M_GOS : 6
U ..> M_DB : 7
U ..> OS_B : 1
OS_B ..> A_RON : 2
U ..> M_DH : 8

@enduml
```

</details>

## Model

![Model](./model.png "Model")

<details>
<summary>plant uml code of image</summary>

```puml
@startuml

title model
namespace Gofermart {
entity "User" as U {
id int
login string
pwd string
}
entity "Order" as O1 {
id int
userId int
orderNumber string
status int
accrualStatus: int
accrual Money
created_at datetime
}
' entity "BalanceAction" as BA {
' value uint
' type int (enum: \n\
' 1 = пополнение на основе\n\
' добавление заказа;\n\
' 2 = списание по инициативе\n\
' пользователя.\n)
' orderId int (default = 0 - нет заказа)
' }

entity "Withdrawal" as W {
id int
userId int
orderNumber string
amount Money
created_at datetime
}
}

namespace Accrual {
entity "Order" as O2 {
+ orderNumber string
+ status string
+ accrual null|int
}
}

U "1" *-d- "many" O1 : create >
'U "1" *-d- "many" BA : read >
'O1 "1" -l- "1" BA : add >
U "1" *-d- "many" W : create >

O1 "1"--"1" O2 : read >

@enduml
```

</details>

## Classes
![Classes](./classes.png "Classes")

<details>
<summary>plant uml code of image</summary>

```puml
@startuml

package "Business" as BL {
package "Services" as BL.S{
class "OrderService" as BL.S.OS {
+ AddOrder()
+ GetAllOrdersByUserID()
+ UpdateOrdersStatuses()
}
class "WithdrawalService" as BL.S.WS {
+ AddWithdrawal()
+ GetAllWithdrawalsByUserID()
}
class "UserService" as BL.S.US {
+ CreateNewUser()
+ GetUserIfPwdValid()
+ GetBalance()
}

package "Contract" as BL.S.C {
interface "OrderRepositoryInterface" as BL.S.C.ORI {}
interface "UserRepositoryInterface" as BL.S.C.URI {}
interface "WithdrawalRepositoryInterface" as BL.S.C.WRI {}
BL.S.C.WRI -[hidden]-> BL.S.C.URI
BL.S.C.URI -[hidden]-> BL.S.C.ORI
}
BL.S.WS -[hidden]-> BL.S.US
BL.S.US -[hidden]-> BL.S.OS

BL.S.OS -o BL.S.C.ORI
BL.S.WS -o BL.S.C.WRI

BL.S.US -lo BL.S.C.URI
BL.S.US -lo BL.S.C.ORI
BL.S.US -lo BL.S.C.WRI

}
package "Entities" as BL.E {
' class "User" as U {}
' class "Order" as O {}
' class "Withdrawal" as W {}
' U *-- O
' note left on link : Заказ был\nдобавлен\nпользователем
' U *-- W
' note left on link : Списание было\nдобавлено\nпользователем
}
}
class "UserController" as UC {
login()
register()
orderList()
addOrder()
balance()
withdraw()
withdrawalList()
}

package "Repositories" as R {
class "OrderRepository" as R.OR {}
class "UserRepository" as R.UR {}
class "WithdrawalRepository" as R.WR {}
R.WR -[hidden]-> R.UR
R.UR -[hidden]-> R.OR
}

BL.S -l-o UC
BL.E o-- BL.S
BL.S.C.ORI <|. R.OR
BL.S.C.URI <|. R.UR
BL.S.C.WRI <|. R.WR

@enduml
```

</details>

## Status mapping on accrual

NEW — заказ загружен в систему, но не попал в обработку;
PROCESSING — вознаграждение за заказ рассчитывается; 200(REGISTERED|PROCESSING)
INVALID — система расчёта вознаграждений отказала в расчёте; 200(INVALID), 204
PROCESSED — данные по заказу проверены и информация о расчёте успешно получена. 200(PROCESSED)

### Accrual statuses
REGISTERED — заказ зарегистрирован, но не начисление не рассчитано;
INVALID — заказ не принят к расчёту, и вознаграждение не будет начислено;
PROCESSING — расчёт начисления в процессе;
PROCESSED — расчёт начисления окончен;
23 changes: 23 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
help: ## Display this help screen
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лайк за мейкфайл

@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
test: test-unit test-func ## run all tests
test-unit: ## run unit tests
go test -v ./tests/Unit/...
echo "\033[1;32mUNIT SUCCESS\033[0m"
test-func: ## run functional tests. Be sure to up DB.
go test -v ./tests/Functional/...
echo "\033[1;32mFUNCTIONAL SUCCESS\033[0m"
build-binary: ## build binary file of the application
go build -o ./build/gophermart ./cmd/gophermart/main.go
run-binary: ## run binary file of the application
./build/gophermart
docker-build-n-run: docker-build docker-run
docker-build:
docker image rm gophermart-img || true
docker build -f docker-files/dev/gophermart/Dockerfile -t gophermart-img --target prod .
docker-run:
docker run -it --rm gophermart-img
mockgen: # generate mocks for project
mockgen -source ./internal/service/contracts.go -destination ./tests/mock/mock_service.go -package mock_contracts
mockgen -source ./pkg/contracts/logger_interface.go -destination ./tests/mock/pkg_contracts.go -package mock_contracts

Empty file added build/.gitkeep
Empty file.
Binary file added classes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 37 additions & 1 deletion cmd/gophermart/main.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
package main

func main() {}
import (
"context"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/rs/zerolog"
"github.com/smamykin/gofermart/internal/container"
"github.com/smamykin/gofermart/pkg/utils"
"os"
)

var logger = zerolog.New(os.Stdout)

func main() {

c, err := container.NewContainer(&logger)
if err != nil {
logger.Error().Err(err).Msgf("error while building container")
return
}
defer c.Close()

logger.Info().Msgf("service started with configuration %#v", c.Config())

ctx, cancel := context.WithCancel(context.Background())
go utils.InvokeFunctionWithInterval(ctx, c.Config().UpdateStatusInterval, func() {
logger.Info().Msgf("update of statuses is started")
err := c.OrderService().UpdateOrdersStatuses()
if err != nil {
logger.Error().Err(err).Msgf("cannot update status")
cancel()
}
})

err = c.Router().Run(c.Config().ServerAddr)
if err != nil {
logger.Error().Msgf("error while running server. error: %s\n", err.Error())
}
}
44 changes: 44 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
version: '3.5'
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

За докеркомпоуз тоже лайк!

services:
accrual:
build:
context: .
dockerfile: docker-files/dev/accrual/Dockerfile
depends_on:
- postgres
ports:
- "8080:8080"
environment:
DATABASE_URI: "postgres://postgres:postgres@postgres:5432/postgres"
# RUN_ADDRESS: "localhost:8080"
gophermart:
build:
context: .
dockerfile: docker-files/dev/gophermart/Dockerfile
target: dev
environment:
DATABASE_URI: "postgres://postgres:postgres@postgres:5432/postgres"
ACCRUAL_SYSTEM_ADDRESS: "http://accrual:8080"
volumes:
- ./:/app
depends_on:
- postgres
ports:
- "8888:8888"
postgres:
image: postgres:15-alpine3.17
ports:
- "54323:5432"
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
PGDATA: /postgresql/data
volumes:
- pgdata:/postgresql/data:rw
# image runs any .sh, .sql, .sql.gz files in this directory (only if database is empty yet)
# Warning: scripts in /docker-entrypoint-initdb.d are only run if you start the container with a data directory that is empty; any pre-existing database will be left untouched on container startup. One common problem is that if one of your /docker-entrypoint-initdb.d scripts fails (which will cause the entrypoint script to exit) and your orchestrator restarts the container with the already initialized data directory, it will not continue on with your scripts.
- ./migrations/init:/docker-entrypoint-initdb.d

volumes:
pgdata:
driver: local
12 changes: 12 additions & 0 deletions docker-files/dev/accrual/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM ubuntu:20.04

COPY ./cmd/accrual/accrual_linux_amd64 /app/accrual/accrual_linux_amd64

ENV RUN_ADDRESS=0.0.0.0:8080

EXPOSE 8080

WORKDIR /app


CMD ["/app/accrual/accrual_linux_amd64", "-a", "$RUN_ADDRESS"]
47 changes: 47 additions & 0 deletions docker-files/dev/gophermart/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
FROM golang:1.20-alpine3.17 as dev


ENV UID=1000
ENV GID=1000
ENV USER=www-data
ENV GROUP=www-data

RUN apk add --update make

RUN adduser -S $USER -G $GROUP

RUN set -xe \
&& apk --no-cache add shadow \
&& usermod -u $UID $USER && groupmod -g $GID $GROUP \
&& apk del shadow



WORKDIR /app

COPY go.mod ./
COPY go.sum ./

RUN go mod download
COPY ./cmd ./cmd
COPY ./internal ./internal
COPY ./migrations ./migrations
COPY ./pkg ./pkg
COPY ./Makefile ./Makefile
COPY ./build ./build

RUN make build-binary

RUN chown $USER:$GROUP . /tmp

USER $USER

EXPOSE 8080

CMD [ "go", "run", "./cmd/gophermart/main.go"]

FROM alpine:3.17 as prod

COPY --from=dev /app/build/gophermart /gophermart

CMD [ "/gophermart" ]
Loading