This commit is contained in:
r8zavetr8v 2024-05-28 23:14:15 +03:00
parent 70f66a4ad4
commit 69aa14bed1
9 changed files with 227 additions and 36 deletions

View File

@ -340,10 +340,43 @@ func (c *transactionsController) NewPayroll(w http.ResponseWriter, r *http.Reque
return presenters.ResponseOK() return presenters.ResponseOK()
} }
func (c *transactionsController) ConfirmPayroll(w http.ResponseWriter, r *http.Request) ([]byte, error) { func (c *transactionsController) ListPayrolls(w http.ResponseWriter, r *http.Request) ([]byte, error) {
return nil, nil req, err := presenters.CreateRequest[domain.ListPayrollsRequest](r)
if err != nil {
return nil, fmt.Errorf("error build request. %w", err)
}
ctx, cancel := context.WithTimeout(r.Context(), time.Second*5)
defer cancel()
organizationID, err := ctxmeta.OrganizationId(ctx)
if err != nil {
return nil, fmt.Errorf("erropr fetch organization id from context. %w", err)
}
ids := make(uuid.UUIDs, len(req.IDs))
for i, idStr := range req.IDs {
id, err := uuid.Parse(idStr)
if err != nil {
return nil, fmt.Errorf("error parse payroll id. %w", err)
}
ids[i] = id
}
payrolls, err := c.chainInteractor.ListPayrolls(ctx, chain.ListPayrollsParams{
OrganizationID: organizationID,
IDs: ids,
Limit: int(req.Limit),
})
if err != nil {
return nil, fmt.Errorf("error fetch payrolls. %w", err)
}
return c.txPresenter.ResponsePayrolls(ctx, payrolls)
} }
func (c *transactionsController) ListPayrolls(w http.ResponseWriter, r *http.Request) ([]byte, error) { func (c *transactionsController) ConfirmPayroll(w http.ResponseWriter, r *http.Request) ([]byte, error) {
return nil, nil return nil, nil
} }

View File

@ -1,30 +0,0 @@
package controllers
import (
"fmt"
"log/slog"
"net/http"
"github.com/emochka2007/block-accounting/internal/interface/rest/domain"
"github.com/emochka2007/block-accounting/internal/interface/rest/presenters"
"github.com/emochka2007/block-accounting/internal/usecase/interactors/chain"
)
type MultisigController interface {
}
type multisigController struct {
log *slog.Logger
chainInteractor chain.ChainInteractor
}
func (c *multisigController) New(w http.ResponseWriter, r *http.Request) ([]byte, error) {
req, err := presenters.CreateRequest[domain.NewMultisigRequest](r)
if err != nil {
return nil, fmt.Errorf("error build new multisig request. %w", err)
}
c.log.Debug("new_multisig", slog.Any("request", req))
panic("implement me!")
}

View File

@ -120,3 +120,8 @@ type NewPayrollRequest struct {
MultisigID string `json:"multisig_id"` MultisigID string `json:"multisig_id"`
Title string `json:"title"` Title string `json:"title"`
} }
type ListPayrollsRequest struct {
IDs []string `json:"ids"`
Limit uint8 `json:"limit"`
}

View File

@ -26,6 +26,8 @@ type TransactionsPresenter interface {
ResponseListTransactions(ctx context.Context, txs []*models.Transaction, cursor string) ([]byte, error) ResponseListTransactions(ctx context.Context, txs []*models.Transaction, cursor string) ([]byte, error)
ResponseMultisigs(ctx context.Context, msgs []models.Multisig) ([]byte, error) ResponseMultisigs(ctx context.Context, msgs []models.Multisig) ([]byte, error)
ResponsePayrolls(ctx context.Context, payrolls []models.Payroll) ([]byte, error)
} }
type transactionsPresenter struct { type transactionsPresenter struct {
@ -223,7 +225,50 @@ func (c *transactionsPresenter) ResponseMultisigs(ctx context.Context, msgs []mo
out, err := json.Marshal(r) out, err := json.Marshal(r)
if err != nil { if err != nil {
return nil, fmt.Errorf("error marshal tx to hal resource. %w", err) return nil, fmt.Errorf("error marshal multisigs to hal resource. %w", err)
}
return out, nil
}
type Payroll struct {
ID string `json:"id"`
Title string `json:"title"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}
func (c *transactionsPresenter) ResponsePayrolls(
ctx context.Context,
payrolls []models.Payroll,
) ([]byte, error) {
organizationID, err := ctxmeta.OrganizationId(ctx)
if err != nil {
return nil, fmt.Errorf("error fetch organization id from context. %w", err)
}
outArray := make([]Payroll, len(payrolls))
for i, pr := range payrolls {
outArray[i] = Payroll{
ID: pr.ID.String(),
Title: pr.Title,
CreatedAt: pr.CreatedAt.UnixMilli(),
UpdatedAt: pr.UpdatedAt.UnixMilli(),
}
}
txsResource := map[string]any{"payrolls": outArray}
r := hal.NewResource(
txsResource,
"/organizations/"+organizationID.String()+"/payrolls",
hal.WithType("paurolls"),
)
out, err := json.Marshal(r)
if err != nil {
return nil, fmt.Errorf("error marshal payrolls to hal resource. %w", err)
} }
return out, nil return out, nil

View File

@ -111,6 +111,10 @@ func (s *Server) buildRouter() {
r.Route("/payrolls", func(r chi.Router) { r.Route("/payrolls", func(r chi.Router) {
r.Get("/", s.handle(s.controllers.Transactions.ListPayrolls, "list_payrolls")) r.Get("/", s.handle(s.controllers.Transactions.ListPayrolls, "list_payrolls"))
r.Post("/", s.handle(s.controllers.Transactions.NewPayroll, "new_payroll")) r.Post("/", s.handle(s.controllers.Transactions.NewPayroll, "new_payroll"))
r.Put("/", s.handle(s.controllers.Transactions.ConfirmPayroll, "confirm_payroll"))
r.Post("/salaries", s.handle(nil, "set_salary"))
r.Get("/salaries", s.handle(nil, "get_salaries"))
}) })
r.Route("/multisig", func(r chi.Router) { r.Route("/multisig", func(r chi.Router) {

View File

@ -30,4 +30,6 @@ type Payroll struct {
Address []byte Address []byte
OrganizationID uuid.UUID OrganizationID uuid.UUID
MultisigID uuid.UUID MultisigID uuid.UUID
CreatedAt time.Time
UpdatedAt time.Time
} }

View File

@ -26,6 +26,7 @@ type ChainInteractor interface {
ListMultisigs(ctx context.Context, params ListMultisigsParams) ([]models.Multisig, error) ListMultisigs(ctx context.Context, params ListMultisigsParams) ([]models.Multisig, error)
PayrollDeploy(ctx context.Context, params PayrollDeployParams) error PayrollDeploy(ctx context.Context, params PayrollDeployParams) error
ListPayrolls(ctx context.Context, params ListPayrollsParams) ([]models.Payroll, error)
} }
type chainInteractor struct { type chainInteractor struct {
@ -428,6 +429,11 @@ func (i *chainInteractor) PayrollDeploy(
return return
} }
i.log.Debug(
"payroll deploy",
slog.Any("response", respObject),
)
if respObject.Address == "" { if respObject.Address == "" {
i.log.Error( i.log.Error(
"error multisig address is empty", "error multisig address is empty",
@ -479,3 +485,47 @@ func (i *chainInteractor) ListMultisigs(
return multisigs, nil return multisigs, nil
} }
type ListPayrollsParams struct {
IDs []uuid.UUID
Limit int
OrganizationID uuid.UUID
}
func (i *chainInteractor) ListPayrolls(
ctx context.Context,
params ListPayrollsParams,
) ([]models.Payroll, error) {
payrolls, err := i.txRepository.ListPayrolls(ctx, transactions.ListPayrollsParams{
IDs: params.IDs,
Limit: int64(params.Limit),
OrganizationID: params.OrganizationID,
})
if err != nil {
return nil, fmt.Errorf("error fetch payrolls from repository. %w", err)
}
return payrolls, nil
}
type NewSalaryParams struct {
OrganizationID uuid.UUID
EmployeeID uuid.UUID
}
func (i *chainInteractor) NewSalary(
ctx context.Context,
params NewSalaryParams,
) error {
user, err := ctxmeta.User(ctx)
if err != nil {
return fmt.Errorf("error fetch user from context. %w", err)
}
organizationID, err := ctxmeta.OrganizationId(ctx)
if err != nil {
return fmt.Errorf("error fetch organization id from context. %w", err)
}
return nil
}

View File

@ -57,6 +57,7 @@ type Repository interface {
ConfirmMultisig(ctx context.Context, params ConfirmMultisigParams) error ConfirmMultisig(ctx context.Context, params ConfirmMultisigParams) error
AddPayrollContract(ctx context.Context, params AddPayrollContract) error AddPayrollContract(ctx context.Context, params AddPayrollContract) error
ListPayrolls(ctx context.Context, params ListPayrollsParams) ([]models.Payroll, error)
} }
type repositorySQL struct { type repositorySQL struct {
@ -688,3 +689,86 @@ func (r *repositorySQL) fetchOwners(ctx context.Context, params fetchOwnersParam
return owners, nil return owners, nil
} }
type ListPayrollsParams struct {
IDs []uuid.UUID
Limit int64
OrganizationID uuid.UUID
}
func (r *repositorySQL) ListPayrolls(ctx context.Context, params ListPayrollsParams) ([]models.Payroll, error) {
payrolls := make([]models.Payroll, 0, len(params.IDs))
if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) error {
query := sq.Select(
"id",
"title",
"address",
"organization_id",
"multisig_id",
"created_at",
"updated_at",
).Where(sq.Eq{
"organization_id": params.OrganizationID,
}).PlaceholderFormat(sq.Dollar)
if params.Limit <= 0 {
params.Limit = 100
}
if len(params.IDs) > 0 {
query = query.Where(sq.Eq{
"id": params.IDs,
})
}
query = query.Limit(uint64(params.Limit))
rows, err := query.RunWith(r.Conn(ctx)).QueryContext(ctx)
if err != nil {
return fmt.Errorf("error fetch payrolls from database. %w", err)
}
defer rows.Close() // todo check error
for rows.Next() {
var (
id uuid.UUID
title string
address []byte
organizationId uuid.UUID
multisigId uuid.UUID
createdAt time.Time
updatedAt time.Time
)
if err = rows.Scan(
&id,
&title,
&address,
&organizationId,
&multisigId,
&createdAt,
&updatedAt,
); err != nil {
return fmt.Errorf("error scan row. %w", err)
}
payrolls = append(payrolls, models.Payroll{
ID: id,
Title: title,
Address: address,
OrganizationID: organizationId,
MultisigID: multisigId,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
})
}
return nil
}); err != nil {
return nil, err
}
return payrolls, nil
}

View File

@ -217,5 +217,3 @@ create table payrolls (
created_at timestamp default current_timestamp, created_at timestamp default current_timestamp,
updated_at timestamp default current_timestamp updated_at timestamp default current_timestamp
); );
create table payrolls