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,14 +13,18 @@ type ClientsDeps struct {
CurrencyURL *models.CurrencyMicroserviceURL
DiscountServiceConfiguration *models.DiscountMicroserviceConfiguration
PaymentServiceConfiguration *models.PaymentMicroserviceConfiguration
VerificationURL *models.VerificationMicroserviceURL
TemplategenURL *models.TemplategenMicroserviceURL
}
type Clients struct {
AuthClient *client.AuthClient
HubadminClient *client.HubadminClient
CurrencyClient *client.CurrencyClient
DiscountClient *client.DiscountClient
PaymentClient *client.PaymentClient
AuthClient *client.AuthClient
HubadminClient *client.HubadminClient
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"
@ -18,8 +15,8 @@ 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
GetRecentTariffs(context.Context, string) ([]models.TariffID, 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

@ -26,13 +26,15 @@ type ConfigurationGRPC struct {
}
type ServiceConfiguration struct {
AuthMicroservice AuthMicroserviceConfiguration
HubadminMicroservice HubadminMicroserviceConfiguration
CurrencyMicroservice CurrencyMicroserviceConfiguration
DiscountMicroservice DiscountMicroserviceConfiguration
PaymentMicroservice PaymentMicroserviceConfiguration
JWT JWTConfiguration
Kafka KafkaConfiguration
AuthMicroservice AuthMicroserviceConfiguration
HubadminMicroservice HubadminMicroserviceConfiguration
CurrencyMicroservice CurrencyMicroserviceConfiguration
DiscountMicroservice DiscountMicroserviceConfiguration
PaymentMicroservice PaymentMicroserviceConfiguration
VerificationMicroservice VerificationMicroserviceConfiguration
TemplategenMicroserviceURL TemplategenMicroserviceConfiguration
JWT JWTConfiguration
Kafka KafkaConfiguration
}
type KafkaConfiguration struct {
@ -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 {
Email string `json:"email"`
TaxNumber string `json:"taxNumber"`
RawDetails RawDetails `json:"rawDetails"`
import "io"
type TemplateGenData struct {
Email string `json:"email"`
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
Logger *zap.Logger
Repository historyRepository
AuthClient authClient
VerificationClient verificationClient
TemlategenClient temlategenClient
}
type Service struct {
logger *zap.Logger
repository historyRepository
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.