refactoring of the sendreports method and adding the necessary clients

This commit is contained in:
pasha1coil 2023-11-26 16:02:01 +03:00
parent 7614255851
commit 3d0db1f54b
10 changed files with 272 additions and 100 deletions

@ -72,7 +72,9 @@ func Run(config *models.Config, logger *zap.Logger) (appErr error) {
HubadminURL: &config.Service.HubadminMicroservice.URL,
CurrencyURL: &config.Service.CurrencyMicroservice.URL,
DiscountServiceConfiguration: &config.Service.DiscountMicroservice,
VerificationURL: &config.Service.VerificationMicroservice.URL,
PaymentServiceConfiguration: &config.Service.PaymentMicroservice,
TemplategenURL: &config.Service.TemplategenMicroserviceURL.URL,
})
repositories := initialize.NewRepositories(initialize.RepositoriesDeps{

@ -13,6 +13,8 @@ type ClientsDeps struct {
CurrencyURL *models.CurrencyMicroserviceURL
DiscountServiceConfiguration *models.DiscountMicroserviceConfiguration
PaymentServiceConfiguration *models.PaymentMicroserviceConfiguration
VerificationURL *models.VerificationMicroserviceURL
TemplategenURL *models.TemplategenMicroserviceURL
}
type Clients struct {
@ -21,6 +23,8 @@ type Clients struct {
CurrencyClient *client.CurrencyClient
DiscountClient *client.DiscountClient
PaymentClient *client.PaymentClient
VerificationClient *client.VerificationClient
TemplateClient *client.TemplateClient
}
func NewClients(deps ClientsDeps) *Clients {
@ -45,5 +49,13 @@ func NewClients(deps ClientsDeps) *Clients {
Logger: deps.Logger,
PaymentServiceHost: deps.PaymentServiceConfiguration.HostGRPC,
}),
VerificationClient: client.NewVerificationClient(client.VerificationClientDeps{
Logger: deps.Logger,
URLs: deps.VerificationURL,
}),
TemplateClient: client.NewTemplateClient(client.TemplateClientDeps{
Logger: deps.Logger,
URLs: deps.TemplategenURL,
}),
}
}

@ -0,0 +1,62 @@
package client
import (
"context"
"fmt"
"go.uber.org/zap"
"log"
"net/url"
"path"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/client"
)
type TemplateClientDeps struct {
Logger *zap.Logger
URLs *models.TemplategenMicroserviceURL
}
type TemplateClient struct {
logger *zap.Logger
urls *models.TemplategenMicroserviceURL
}
func NewTemplateClient(deps TemplateClientDeps) *TemplateClient {
if deps.Logger == nil {
log.Panicln("logger is nil on <NewTemplateClient>")
}
if deps.URLs == nil {
log.Panicln("urls is nil on <NewTemplateClient>")
}
return &TemplateClient{
logger: deps.Logger,
urls: deps.URLs,
}
}
func (receiver *TemplateClient) PostToTemplategen(ctx context.Context, data any) errors.Error {
tmplURL, err := url.Parse(receiver.urls.Templategen)
if err != nil {
return errors.New(
fmt.Errorf("failed to parse URL on <PostToTemplategen>: %w", err),
errors.ErrInternalError,
)
}
tmplURL.Path = path.Join(tmplURL.Path)
_, err = client.Post[interface{}, models.FastifyError](ctx, &client.RequestSettings{
URL: tmplURL.String(),
Headers: map[string]string{"Content-Type": "multipart/form-data"},
Body: data,
})
if err != nil {
return errors.New(err, errors.ErrInternalError)
}
return nil
}

@ -0,0 +1,58 @@
package client
import (
"context"
"fmt"
"go.uber.org/zap"
"log"
"net/url"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/client"
)
type VerificationClientDeps struct {
Logger *zap.Logger
URLs *models.VerificationMicroserviceURL
}
type VerificationClient struct {
logger *zap.Logger
urls *models.VerificationMicroserviceURL
}
func NewVerificationClient(deps VerificationClientDeps) *VerificationClient {
if deps.Logger == nil {
log.Panicln("logger is nil on <NewVerificationClient>")
}
if deps.URLs == nil {
log.Panicln("urls is nil on <NewVerificationClient>")
}
return &VerificationClient{
logger: deps.Logger,
urls: deps.URLs,
}
}
func (receiver *VerificationClient) GetVerification(ctx context.Context, userID string) (*models.Verification, errors.Error) {
verifURL, err := url.JoinPath(receiver.urls.Verification, userID)
if err != nil {
return nil, errors.New(
fmt.Errorf("failed to join path on <GetVerification> of <VerificationClient>: %w", err),
errors.ErrInternalError,
)
}
response, err := client.Get[models.Verification, models.FastifyError](ctx, &client.RequestSettings{
URL: verifURL,
Headers: map[string]string{"Content-Type": "application/json"},
})
if err != nil {
return nil, errors.New(err, errors.ErrInternalError)
}
return response.Body, nil
}

@ -1,15 +1,12 @@
package history
import (
"bytes"
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/labstack/echo/v4"
"go.uber.org/zap"
"log"
"net/http"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/dto"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/swagger"
@ -19,7 +16,7 @@ import (
type historyService interface {
GetHistoryList(context.Context, *dto.GetHistories) (*models.PaginationResponse[models.History], errors.Error)
GetRecentTariffs(context.Context, string) ([]models.TariffID, errors.Error) // new
GetHistoryById(context.Context, string) (*models.ReportHistory, errors.Error) // new
GetHistoryById(context.Context, string) errors.Error // new
}
type Deps struct {
@ -98,75 +95,14 @@ func (receiver *Controller) GetRecentTariffs(ctx echo.Context) error {
}
// TODO:tests.
// скорее всего нужно будет передавать токен авторизации но пока не точно, также брать урлы из переменных окружения или конфига
// также сделать рефакторинг, пока выглядит не очень
func (receiver *Controller) GetHistoryById(ctx echo.Context) error {
func (receiver *Controller) SendReport(ctx echo.Context) error {
historyID := ctx.Param("id")
// Получаем запись из истории по идентификатору
historyRecord, err := receiver.historyService.GetHistoryById(ctx.Request().Context(), historyID)
err := receiver.historyService.GetHistoryById(ctx.Request().Context(), historyID)
if err != nil {
receiver.logger.Error("failed to get history record on <GetHistoryById> of <HistoryController>", zap.Error(err))
receiver.logger.Error("failed to send report on <SendReport> of <HistoryController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
// Проверяем, что запись имеет ключ "payCart"
if historyRecord.Key != models.CustomerHistoryKeyPayCart {
err := errors.NewWithMessage("invalid history record key", errors.ErrInvalidArgs)
receiver.logger.Error("invalid history record key", zap.Error(err))
return errors.HTTP(ctx, err)
}
// Получаем данные о верификации
client := &http.Client{}
url := fmt.Sprintf("http://example/verification/%s", historyRecord.UserID)
response, _ := client.Get(url)
defer response.Body.Close()
var verificationResponse models.Verification
decoder := json.NewDecoder(response.Body)
if err := decoder.Decode(&verificationResponse); err != nil {
err := errors.NewWithMessage(err.Error(), errors.ErrInternalError)
receiver.logger.Error("failed to decode verification response", zap.Error(err))
return errors.HTTP(ctx, err)
}
if !verificationResponse.Accepted {
err := errors.NewWithMessage("Verification not accepted", errors.ErrNoAccess)
receiver.logger.Error("verification not accepted", zap.Error(err))
return errors.HTTP(ctx, err)
}
// Получаем email
url = fmt.Sprintf("http://example/user/%s", historyRecord.UserID)
response, _ = client.Get(url)
var userResponse models.User
decoder = json.NewDecoder(response.Body)
if err := decoder.Decode(&userResponse); err != nil {
err := errors.NewWithMessage(err.Error(), errors.ErrInternalError)
receiver.logger.Error("failed to decode verification response", zap.Error(err))
return errors.HTTP(ctx, err)
}
// Получаем данные для передачи в templategen, возможно придется менять
generatorRequest := models.GeneratorRequest{
Email: userResponse.Email,
TaxNumber: verificationResponse.TaxNumber,
RawDetails: historyRecord.RawDetails,
}
// Маршалируем данные в JSON
requestBody, _ := json.Marshal(generatorRequest)
if err != nil {
return errors.HTTP(ctx, err)
}
generatorURL := "http://example/generator/service"
response, _ = client.Post(generatorURL, "application/json", bytes.NewBuffer(requestBody))
if err != nil {
return errors.HTTP(ctx, err)
}
return nil
return ctx.JSON(http.StatusOK, nil)
}

@ -35,7 +35,7 @@ type walletController interface {
type historyController interface {
GetHistoryList(ctx echo.Context, params GetHistoryParams) error
GetRecentTariffs(ctx echo.Context) error
GetHistoryById(ctx echo.Context) error
SendReport(ctx echo.Context) error
}
type Deps struct {
@ -153,7 +153,7 @@ func (receiver *API) GetRecentTariffs(ctx echo.Context) error {
}
func (receiver *API) SendReport(ctx echo.Context) error {
return receiver.historyController.GetHistoryById(ctx)
return receiver.historyController.SendReport(ctx)
}
// Wallet

@ -31,6 +31,8 @@ type ServiceConfiguration struct {
CurrencyMicroservice CurrencyMicroserviceConfiguration
DiscountMicroservice DiscountMicroserviceConfiguration
PaymentMicroservice PaymentMicroserviceConfiguration
VerificationMicroservice VerificationMicroserviceConfiguration
TemplategenMicroserviceURL TemplategenMicroserviceConfiguration
JWT JWTConfiguration
Kafka KafkaConfiguration
}
@ -65,6 +67,14 @@ type CurrencyMicroserviceConfiguration struct {
URL CurrencyMicroserviceURL
}
type VerificationMicroserviceConfiguration struct {
URL VerificationMicroserviceURL
}
type TemplategenMicroserviceConfiguration struct {
URL TemplategenMicroserviceURL
}
type PaymentMicroserviceConfiguration struct {
HostGRPC string `env:"PAYMENT_MICROSERVICE_GRPC_HOST,required"`
}
@ -84,3 +94,11 @@ type HubadminMicroserviceURL struct {
type CurrencyMicroserviceURL struct {
Translate string `env:"CURRENCY_MICROSERVICE_TRANSLATE_URL,required"`
}
type VerificationMicroserviceURL struct {
Verification string `env:"VERIFICATION_MICROSERVICE_USER_URL,required"`
}
type TemplategenMicroserviceURL struct {
Templategen string `env:"TEMPLATEGEN_MICROSERVICE_URL,required"`
}

@ -1,7 +1,14 @@
package models
type GeneratorRequest struct {
import "io"
type TemplateGenData struct {
Email string `json:"email"`
TaxNumber string `json:"taxNumber"`
RawDetails RawDetails `json:"rawDetails"`
Data Data `json:"data"`
File io.Reader `json:"file"`
}
type Data struct {
TaxNumber string `json:"taxnumber"`
History *ReportHistory `json:"history"`
}

@ -1,6 +1,7 @@
package history
import (
"bytes"
"context"
"fmt"
"log"
@ -20,14 +21,32 @@ type historyRepository interface {
GetHistoryById(context.Context, string) (*models.ReportHistory, errors.Error)
}
type authClient interface {
GetUser(ctx context.Context, userID string) (*models.User, errors.Error)
}
type verificationClient interface {
GetUser(ctx context.Context, userID string) (*models.Verification, errors.Error)
}
type temlategenClient interface {
SendData(ctx context.Context, data models.TemplateGenData) errors.Error
}
type Deps struct {
Logger *zap.Logger
Repository historyRepository
AuthClient authClient
VerificationClient verificationClient
TemlategenClient temlategenClient
}
type Service struct {
logger *zap.Logger
repository historyRepository
AuthClient authClient
VerificationClient verificationClient
TemlategenClient temlategenClient
}
func New(deps Deps) *Service {
@ -39,9 +58,14 @@ func New(deps Deps) *Service {
log.Panicln("repository is nil on <New (history service)>")
}
if deps.AuthClient == nil {
log.Panicln("auth client is nil on <New (account service)>")
}
return &Service{
logger: deps.Logger,
repository: deps.Repository,
AuthClient: deps.AuthClient,
}
}
@ -116,10 +140,10 @@ func (receiver *Service) GetRecentTariffs(ctx context.Context, userID string) ([
return tariffs, nil
}
func (receiver *Service) GetHistoryById(ctx context.Context, historyID string) (*models.ReportHistory, errors.Error) {
func (receiver *Service) GetHistoryById(ctx context.Context, historyID string) errors.Error {
if historyID == "" {
receiver.logger.Error("user id is missing in <FindByID> of <HistoryService>")
return nil, errors.New(
receiver.logger.Error("history id is missing in <GetHistoryById> of <HistoryService>")
return errors.New(
fmt.Errorf("history id is missing: %w", errors.ErrInvalidArgs),
errors.ErrInvalidArgs,
)
@ -128,12 +152,65 @@ func (receiver *Service) GetHistoryById(ctx context.Context, historyID string) (
tariffs, err := receiver.repository.GetHistoryById(ctx, historyID)
if err != nil {
receiver.logger.Error(
"failed to find by id in <FindByID> of <HistoryService>",
"failed to get history by id in <GetHistoryById> of <HistoryService>",
zap.String("historyID", historyID),
zap.Error(err),
)
return nil, err
return err
}
return tariffs, nil
if tariffs.Key != models.CustomerHistoryKeyPayCart {
receiver.logger.Error(
"invalid history record key",
zap.String("historyID", historyID),
zap.Error(err),
)
return err
}
verifuser, err := receiver.VerificationClient.GetUser(ctx, tariffs.UserID)
if err != nil {
receiver.logger.Error("failed to get user verification on <GetHistoryById> of <HistoryService>",
zap.Error(err),
zap.String("userID", tariffs.UserID),
)
return err
}
if !verifuser.Accepted {
receiver.logger.Error(
"verification not accepted",
zap.String("userID", tariffs.UserID),
zap.Error(err),
)
return err
}
authuser, err := receiver.AuthClient.GetUser(ctx, tariffs.UserID)
if err != nil {
receiver.logger.Error("failed to get user on <GetHistoryById> of <HistoryService>",
zap.Error(err),
zap.String("userID", tariffs.UserID),
)
return err
}
data := models.TemplateGenData{
Email: authuser.Email,
Data: models.Data{
TaxNumber: verifuser.TaxNumber,
History: tariffs,
},
File: bytes.NewReader([]byte("./report.docx")),
}
err = receiver.TemlategenClient.SendData(ctx, data)
if err != nil {
receiver.logger.Error("failed to send report to user on <GetHistoryById> of <HistoryService>",
zap.Error(err),
zap.String("userID", tariffs.UserID),
)
return err
}
return nil
}

BIN
report.docx Normal file

Binary file not shown.